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: Thu, 09 Oct 2003 21:22:10 -0400

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

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

Modified files:
        src/datasources: GConnections.py GDataObjects.py GDataSource.py 
        src/datasources/drivers/DBSIG2: Driver.py __init__.py 
        src/datasources/drivers/adodbapi/adodbapi: __init__.py 
        src/datasources/drivers/appserver/appserver: __init__.py 
        src/datasources/drivers/db2/db2: __init__.py 
        src/datasources/drivers/dbf/dbf: __init__.py 
        src/datasources/drivers/gadfly/gadfly: __init__.py 
        src/datasources/drivers/informix/informix: __init__.py 
        src/datasources/drivers/ingres/ingres: __init__.py 
        src/datasources/drivers/interbase/interbase: __init__.py 
        src/datasources/drivers/mysql/mysql: __init__.py 
        src/datasources/drivers/odbc: __init__.py 
        src/datasources/drivers/odbc/wodbc: __init__.py 
        src/datasources/drivers/oracle/Base: __init__.py 
        src/datasources/drivers/oracle/cxoracle: Driver.py __init__.py 
        src/datasources/drivers/oracle/dcoracle: Driver.py __init__.py 
        src/datasources/drivers/postgresql/Base: __init__.py 
        src/datasources/drivers/postgresql/popy: __init__.py 
        src/datasources/drivers/postgresql/psycopg: __init__.py 
        src/datasources/drivers/postgresql/pygresql: __init__.py 
        src/datasources/drivers/postgresql/pypgsql: __init__.py 
        src/datasources/drivers/sapdb/sapdb: __init__.py 
        src/datasources/drivers/special/configfile: __init__.py 
        src/datasources/drivers/special/static: Driver.py __init__.py 
        src/datasources/drivers/special/unbound: Driver.py __init__.py 
        src/datasources/drivers/sqlite/sqlite: __init__.py 
        src/datasources/drivers/sqlrelay/sqlrelay: __init__.py 
        src/datasources/drivers/sybase/sybase: __init__.py 
Added files:
        src/datasources: GConnection.py GIntrospection.py 
        src/datasources/drivers/DBSIG2: Connection.py DataObject.py 
                                        RecordSet.py ResultSet.py 
        src/datasources/drivers/adodbapi/Schema/Discovery: 
                                                           Introspection.py 
        src/datasources/drivers/adodbapi/adodbapi: Connection.py 
                                                   DataObject.py 
        src/datasources/drivers/appserver/Schema/Discovery: 
                                                            Introspection.py 
        src/datasources/drivers/appserver/appserver: Connection.py 
                                                     DataObject.py 
                                                     RecordSet.py 
                                                     ResultSet.py 
        src/datasources/drivers/db2/Schema/Discovery: Introspection.py 
        src/datasources/drivers/db2/db2: Connection.py 
        src/datasources/drivers/dbf/Schema/Discovery: Introspection.py 
        src/datasources/drivers/dbf/dbf: Connection.py DataObject.py 
                                         RecordSet.py ResultSet.py 
        src/datasources/drivers/gadfly/Schema/Discovery: 
                                                         Introspection.py 
        src/datasources/drivers/gadfly/gadfly: Connection.py 
                                               DataObject.py 
                                               RecordSet.py ResultSet.py 
        src/datasources/drivers/informix/Schema/Discovery: 
                                                           Introspection.py 
        src/datasources/drivers/informix/informix: Connection.py 
                                                   DataObject.py 
                                                   RecordSet.py 
                                                   ResultSet.py 
        src/datasources/drivers/ingres/Schema/Discovery: 
                                                         Introspection.py 
        src/datasources/drivers/ingres/ingres: Connection.py 
                                               DataObject.py 
                                               RecordSet.py ResultSet.py 
        src/datasources/drivers/interbase/Schema/Discovery: 
                                                            Introspection.py 
        src/datasources/drivers/interbase/interbase: Connection.py 
                                                     DataObject.py 
                                                     RecordSet.py 
                                                     ResultSet.py 
        src/datasources/drivers/mysql/Schema/Discovery: Introspection.py 
        src/datasources/drivers/mysql/mysql: Connection.py DataObject.py 
                                             RecordSet.py ResultSet.py 
        src/datasources/drivers/odbc/wodbc: Connection.py DataObject.py 
                                            RecordSet.py ResultSet.py 
        src/datasources/drivers/oracle/Base: Connection.py DataObject.py 
                                             RecordSet.py ResultSet.py 
        src/datasources/drivers/oracle/Schema/Discovery: 
                                                         Introspection.py 
        src/datasources/drivers/postgresql/Base: Connection.py 
                                                 DataObject.py 
                                                 RecordSet.py 
                                                 ResultSet.py 
        src/datasources/drivers/postgresql/Schema/Discovery: 
                                                             Introspection.py 
        src/datasources/drivers/sapdb/Schema/Discovery: Introspection.py 
        src/datasources/drivers/sapdb/sapdb: Connection.py DataObject.py 
                                             RecordSet.py ResultSet.py 
        src/datasources/drivers/sqlite/Schema/Discovery: 
                                                         Introspection.py 
        src/datasources/drivers/sqlite/sqlite: Connection.py 
                                               DataObject.py 
                                               RecordSet.py ResultSet.py 
        src/datasources/drivers/sqlrelay/sqlrelay: Connection.py 
                                                   DataObject.py 
                                                   RecordSet.py 
                                                   ResultSet.py 
        src/datasources/drivers/sybase/Schema/Discovery: 
                                                         Introspection.py 
        src/datasources/drivers/sybase/sybase: Connection.py 
                                               DataObject.py 
                                               RecordSet.py ResultSet.py 
Removed files:
        src/datasources/drivers/adodbapi/adodbapi: Driver.py 
        src/datasources/drivers/appserver/appserver: Driver.py 
        src/datasources/drivers/db2/db2: Driver.py 
        src/datasources/drivers/dbf/dbf: Driver.py 
        src/datasources/drivers/gadfly/gadfly: Driver.py 
        src/datasources/drivers/informix/informix: Driver.py 
        src/datasources/drivers/ingres/ingres: Driver.py 
        src/datasources/drivers/interbase/interbase: Driver.py 
        src/datasources/drivers/mysql/mysql: Driver.py 
        src/datasources/drivers/odbc/mxodbc: Driver.py __init__.py 
        src/datasources/drivers/odbc/wodbc: Driver.py 
        src/datasources/drivers/oracle/Base: Driver.py 
        src/datasources/drivers/postgresql/Base: Driver.py 
        src/datasources/drivers/postgresql/popy: Driver.py 
        src/datasources/drivers/postgresql/psycopg: Driver.py 
        src/datasources/drivers/postgresql/pygresql: Driver.py 
        src/datasources/drivers/postgresql/pypgsql: Driver.py 
        src/datasources/drivers/sapdb/sapdb: Driver.py 
        src/datasources/drivers/sqlite/sqlite: Driver.py 
        src/datasources/drivers/sqlrelay/sqlrelay: Driver.py 
        src/datasources/drivers/sybase/sybase: Driver.py 

Log message:
        moving my datasource changes into a branch (datasource-cleanup)

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/GConnection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/GIntrospection.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&tr2=1.52.2.1&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&tr2=1.72.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/GDataSource.py.diff?only_with_tag=datasource-cleanup&tr1=1.64&tr2=1.64.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/DBSIG2/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/DBSIG2/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/DBSIG2/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/DBSIG2/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/DBSIG2/Driver.py.diff?only_with_tag=datasource-cleanup&tr1=1.76&tr2=1.76.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/DBSIG2/__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/adodbapi/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/adodbapi/adodbapi/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/adodbapi/adodbapi/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/adodbapi/adodbapi/__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/appserver/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/appserver/appserver/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/appserver/appserver/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/appserver/appserver/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/appserver/appserver/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/appserver/appserver/__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/db2/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/db2/db2/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/db2/db2/__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/dbf/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/dbf/dbf/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/dbf/dbf/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/dbf/dbf/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/dbf/dbf/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/dbf/dbf/__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/gadfly/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/gadfly/gadfly/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/gadfly/gadfly/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/gadfly/gadfly/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/gadfly/gadfly/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/gadfly/gadfly/__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/informix/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/informix/informix/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/informix/informix/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/informix/informix/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/informix/informix/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/informix/informix/__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/ingres/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/ingres/ingres/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/ingres/ingres/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/ingres/ingres/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/ingres/ingres/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/ingres/ingres/__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/interbase/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/interbase/interbase/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/interbase/interbase/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/interbase/interbase/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/interbase/interbase/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/interbase/interbase/__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/mysql/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/mysql/mysql/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/mysql/mysql/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/mysql/mysql/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/mysql/mysql/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/mysql/mysql/__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/odbc/__init__.py.diff?only_with_tag=datasource-cleanup&tr1=1.2&tr2=1.2.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/odbc/wodbc/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/odbc/wodbc/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/odbc/wodbc/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/odbc/wodbc/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/odbc/wodbc/__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/oracle/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/oracle/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/oracle/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/oracle/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/oracle/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/oracle/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/oracle/cxoracle/Driver.py.diff?only_with_tag=datasource-cleanup&tr1=1.20&tr2=1.20.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/oracle/cxoracle/__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/oracle/dcoracle/Driver.py.diff?only_with_tag=datasource-cleanup&tr1=1.24&tr2=1.24.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/oracle/dcoracle/__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/postgresql/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/postgresql/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/postgresql/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/postgresql/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/postgresql/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/postgresql/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/postgresql/popy/__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/postgresql/psycopg/__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/postgresql/pygresql/__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/postgresql/pypgsql/__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/sapdb/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/sapdb/sapdb/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/sapdb/sapdb/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/sapdb/sapdb/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/sapdb/sapdb/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/sapdb/sapdb/__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/special/configfile/__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/special/static/Driver.py.diff?only_with_tag=datasource-cleanup&tr1=1.9&tr2=1.9.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/special/static/__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/special/unbound/Driver.py.diff?only_with_tag=datasource-cleanup&tr1=1.6&tr2=1.6.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/special/unbound/__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/sqlite/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/sqlite/sqlite/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/sqlite/sqlite/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/sqlite/sqlite/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/sqlite/sqlite/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/sqlite/sqlite/__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/sqlrelay/sqlrelay/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/sqlrelay/sqlrelay/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/sqlrelay/sqlrelay/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/sqlrelay/sqlrelay/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/sqlrelay/sqlrelay/__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/sybase/Schema/Discovery/Introspection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/sybase/sybase/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/sybase/sybase/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/sybase/sybase/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/sybase/sybase/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/sybase/sybase/__init__.py.diff?only_with_tag=datasource-cleanup&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text

Patches:
Index: gnue-common/src/datasources/GConnection.py
diff -c /dev/null gnue-common/src/datasources/GConnection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:37 2003
--- gnue-common/src/datasources/GConnection.py  Thu Oct  9 21:21:08 2003
***************
*** 0 ****
--- 1,9 ----
+ 
+ 
+ System Init:
+    +-- GConnections initializes
+    +-- GParser initializes:
+      +-- GDataSource loaded
+    +-- GDataSources Intialized
+      +-- GConnection.getDataObject()
+        +--
Index: gnue-common/src/datasources/GConnections.py
diff -c /dev/null gnue-common/src/datasources/GConnections.py:1.52.2.1
*** /dev/null   Thu Oct  9 21:21:38 2003
--- gnue-common/src/datasources/GConnections.py Thu Oct  9 21:21:08 2003
***************
*** 0 ****
--- 1,464 ----
+ #
+ # 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:
+ # GConnections.py
+ #
+ # DESCRIPTION:
+ # Class that loads connection definition files and maintains
+ # database connections.
+ #
+ # NOTES:
+ #
+ # HISTORY:
+ #
+ 
+ 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
+ class Error(StandardError):
+   # Base error
+   pass
+ 
+ class NotFoundError (Error):
+   # Raised if a requested connection name does not
+   # exist in the Connections Definition File.
+   pass
+ 
+ class AdapterNotInstalled (Error):
+   # Raised if a provider is requested for which
+   # the python libraries are not installed.
+   pass
+ 
+ class InvalidFormatError (Error):
+   # Raised if the Connections Definition File is
+   # in an unreadable format.
+   pass
+ 
+ LoginError = GDataObjects.LoginError
+ 
+ 
+ class GConnections:
+ 
+   def __init__(self, location, loginHandler=None):
+ 
+     self._loginHandler = loginHandler
+     self._parser = ConfigParser()
+     self._location = location
+     self._authenticatedUsers = {}
+ 
+     GDebug.printMesg(1,'Conn File: "%s"' % location)
+ 
+     if len(location):
+       fileHandle = openResource(location)
+ 
+       try:
+         self._parser.readfp(fileHandle)
+       except DuplicateSectionError:
+         tmsg =  _('The connections file has duplicate source 
definitions.\n\nFile: %s') \
+               % location
+         raise InvalidFormatError, tmsg
+       except MissingSectionHeaderError:
+         tmsg = _('The connections file has no source definitions.\n\nFile: 
%s') \
+               % location
+         raise InvalidFormatError, tmsg
+       except:
+         tmsg =  _('The connections file cannot be parsed.\n\nFile: %s') % 
location
+         raise InvalidFormatError, tmsg
+ 
+     self._openConnections = {}
+ 
+     self._primaries = {}
+     self._aliases = {}
+     self._definitions = {}
+ 
+ 
+     # Read all the sections into a dict
+     # and make a note of all alias names
+     for section in self._parser.sections():
+        self._primaries[section]={}
+        for att in self._parser.options(section):
+          if att == 'aliases':
+            for alias in 
string.split(string.lower(self._parser.get(section,att))):
+              self._aliases[alias] = section
+          else:
+            self._primaries[section][att] = self._parser.get(section, att)
+ 
+     # Fill in any aliases with their parameters
+     for alias in self._aliases.keys():
+       section = self._aliases[alias]
+       self._aliases[alias] = copy.copy(self._primaries[section])
+       self._aliases[alias]['_alias_of'] = section
+ 
+ 
+     self._definitions.update(self._aliases)
+     self._definitions.update(self._primaries)
+ 
+ 
+ 
+   def setLoginHandler(self, loginHandler):
+     self._loginHandler = loginHandler
+ 
+ 
+   def hasConnectionParameters(self, connection_name):
+     return self._definitions.has_key(connection_name)
+ 
+ 
+   def getConnectionParameter(self, connection_name, attribute, default=None):
+     try:
+       definition = self._definitions[connection_name]
+       try:
+         return definition[attribute]
+       except:
+         return default
+     except KeyError:
+       tmsg = _('The connections file does not contain a definition \n       
for "%s".\n\nFile: %s') \
+             % (connection_name, self._location)
+       raise NotFoundError, tmsg
+ 
+ 
+   #
+   # Returns an dictionary of dictionaries describing all connections:
+   #  {connection name: {att name: value}}
+   #
+   def getConnectionNames(self, includeAliases=1):
+     if includeAliases:
+       return self._definitions.keys()
+     else:
+       return self._primaries.keys()
+ 
+ 
+   #
+   # Returns an dictionary of dictionaries describing all connections:
+   #  {connection name: {att name: value}}
+   #
+   def getAllConnectionParameters(self, includeAliases=1):
+     if includeAliases:
+       return copy.deepcopy(self._definitions)
+     else:
+       return copy.deepcopy(self._primaries)
+ 
+ 
+   #
+   # Returns a dictionary describing a connection:
+   #  {att name: value}
+   #
+   def getConnectionParameters(self, connection_name):
+     try:
+       return copy.deepcopy(self._definitions[connection_name])
+     except KeyError:
+       tmsg = _('The connections file does not contain a definition \n       
for "%s".\n\nFile: %s') \
+             % (connection_name, self._location)
+       raise NotFoundError, tmsg
+ 
+ 
+   #
+   # Add a connection entry (session specific; i.e., doesn't add
+   # to the connections.conf file, but to the current instance's
+   # list of available connections.
+   #
+   def addConnectionSpecification (self, name, parameters):
+     self._definitions[string.lower(name)] = copy.copy(parameters)
+ 
+ 
+ 
+   def getConnection(self, connection_name):
+ 
+     print "getConnection: %s" % (connection_name)
+ 
+     connection_name = connection_name.lower()
+ 
+     try:
+       return self._openConnections[connection_name]
+     except KeyError:
+       pass
+ 
+     # Support for multiple open connections
+     # to same database.
+     # Specify as 'gnue:1', 'gnue:2', etc, to open
+     # two actual connections to 'gnue', each with
+     # their own transactions, etc.
+     try:
+       connection_base = connection_name.split(':',1)[0]
+     except:
+       connection_base = connection_name
+       extra = ""
+ 
+     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)
+ 
+     parameters = self.getConnectionParameters(connection_base)
+ 
+     driver = parameters['provider'].lower().replace('/','.')
+     behavior = parameters.get('behavior','').lower().replace('/','.')
+ 
+     try:
+       basedriver, extradriver =driver.split('.',1)
+     except:
+       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:
+       dbdriver = _get_dbdriver(basemodule + extradriver)
+ 
+     if not dbdriver:
+       tmsg = _("No database driver found for provider type '%s'") % driver
+       raise GDataObjects.ProviderNotSupportedError, tmsg
+ 
+ 
+     conn = dbdriver.Connection(self, parameters)
+     self._openConnections[connection_name] = conn
+     return conn
+ 
+ 
+ 
+   #
+   # Return a database provider object
+   #
+   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
+ 
+ 
+ 
+   #
+   # Has a connection been initialized/established?
+   #
+   # TODO: this was likely broken
+   def isConnectionActive(self, connection):
+     return self._openConnections.has_key(string.lower(connection))
+ 
+ 
+   #
+   # Get a data connection for a specified database
+   #
+   def requestConnection(self, dataObject):
+ 
+     print "requestConnection: %s" % dataObject
+ 
+     # Support for multiple open connections
+     # to same database.
+     # Specify as 'gnue:1', 'gnue:2', etc, to open
+     # two actual connections to 'gnue', each with
+     # their own transactions, etc.
+ 
+     self.loginToConnection(dataObject._connection)
+ 
+ 
+   def loginToConnection(self, connection):
+ 
+     print "loginToConnection: %s" % connection
+     try:
+       connected = connection.__connected
+     except:
+       connected = 0
+ 
+     if not connected:
+       loginData = connection.parameters
+       try:
+         # load the user's netrc file:
+         # a sample .netrc could look like:
+         # <.netrc begin>
+         # machine 'gnue://my_connection/'
+         # login 'mylogin'
+         # password 'mypassword'
+         # EOF
+         # (Remark: if .netrc should work under Win32 you have to
+       #  set the HOME environement variable [SET HOME=...])
+ 
+         netrcData = netrc.netrc().authenticators(
+               "'gnue://%s/'" % base )
+         if netrcData!=None:
+           GDebug.printMesg(5, 'Read the user\'s .netrc file')
+           loginData['_username'] = netrcData[0][1:-1]
+           loginData['_password'] = netrcData[2][1:-1]
+           GDebug.printMesg(5, 'Found useful stuff for connection %s in the 
user\'s .netrc file' % connection_name)
+       except (IOError,netrc.NetrcParseError,KeyError):
+         pass
+ 
+       if (loginData.has_key('username')):
+         loginData['_username'] = loginData['username']
+         del loginData['username']
+ 
+       if (loginData.has_key('password')):
+         loginData['_password'] = loginData['password']
+         del loginData['password']
+ 
+       # Load
+       if loginData.has_key('custom_auth'):
+         authenticator = dyn_import(loginData['custom_auth']).Authenticator()
+         checkFields = 
authenticator.getLoginFields(connection.getLoginFields())
+       else:
+         checkFields = connection.getLoginFields()
+         authenticator = None
+ 
+       haveAllInformation = 1
+       for rf, dummy1, dummy2 in checkFields:
+         if not (loginData.has_key(rf) and loginData[rf] != None):
+           haveAllInformation = 0
+           break
+ 
+       if haveAllInformation:
+ #        try:
+ #          self._authenticatedUsers[base] = loginData['_username']
+ #        except KeyError:
+ #          self._authenticatedUsers[base] = None
+ 
+         if authenticator:
+           connection.connect(authenticator.login(loginData))
+         else:
+           connection.connect(loginData)
+ 
+       else:
+         attempts = 4
+ 
+         GDebug.printMesg(5,'Getting new data connection to %s' % 
connection_name)
+ 
+         errortext = None
+         while attempts:
+ 
+           try:
+ 
+             # Ask the UI to prompt for our login data
+             loginData.update(self._loginHandler.getLogin(
+               [connection_base,
+                self.getConnectionParameter(connection_base,'comment',''),
+                checkFields], errortext))
+ 
+             # Add to authenticated user list
+             try:
+               self._authenticatedUsers[connection] = loginData['_username']
+             except KeyError:
+               self._authenticatedUsers[connection] = None
+ 
+             # Ask the data object to connect to the database
+             if authenticator:
+               connection.connect(authenticator.login(loginData))
+             else:
+               connection.connect(loginData)
+ 
+             # We're done!
+             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?!!!
+             # Ok, then "those address@hidden users"
+             attempts = attempts - 1
+             errortext = string.replace("%s" % error,'\n','')
+           self._loginHandler.destroyLoginDialog()
+ 
+             if not attempts:
+               # 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
+ 
+ 
+   def getAuthenticatedUser(self, connection=None):
+     try:
+       if connection == None:
+         return self._authenticatedUsers[self._authenticatedUsers.keys()[0]]
+       else:
+         return self._authenticatedUsers[connection]
+     except (KeyError, IndexError):
+       return None
+ 
+ 
+ 
+ #
+ # Load the correct DBdriver from gnue/common/datasources/drivers/*/
+ #
+ 
+ def _find_base_driver (driver, modules, path=[]):
+   if driver in modules:
+     return 'gnue.common.datasources.drivers.' + string.join(path + 
[driver],'.')
+   else:
+     for module in modules:
+       print "trying module: %s" % module
+       try:
+         m = dyn_import ('gnue.common.datasources.drivers.' + string.join(path 
+ [module],'.')).DRIVERS
+         rs = _find_base_driver(driver, m, path + [module])
+         if rs:
+           return rs
+       except (AttributeError, ImportError), err:
+         pass
+         ##print "Not in " + 'gnue.common.datasources.drivers.' + 
string.join(path + [module],'.')
+ 
+ 
+ def _get_dbdriver (driver):
+   dbdriver = None
+ 
+   try:
+     dbdriver = dyn_import("%s" % (driver))
+     dbdriver.Connection
+   except:
+     GDebug.printMesg(1,'%s is not a dbdriver' % ( driver))
+     try:
+       drivers = dyn_import("%s" % (driver)).DRIVERS
+       for d in drivers:
+         dbdriver = _get_dbdriver(driver + "." + d )
+         if dbdriver:
+           return dbdriver
+     except (ImportError, AttributeError):
+       GDebug.printMesg(1,'%s does not contain dbdrivers' % (driver))
+ 
+   return dbdriver
+ 
Index: gnue-common/src/datasources/GDataObjects.py
diff -c /dev/null gnue-common/src/datasources/GDataObjects.py:1.72.2.1
*** /dev/null   Thu Oct  9 21:21:38 2003
--- gnue-common/src/datasources/GDataObjects.py Thu Oct  9 21:21:08 2003
***************
*** 0 ****
--- 1,817 ----
+ #
+ # 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:
+ # 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 = {}
+ 
+     # 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 = ''
+     self.type = ''
+     self.__dict__.update(attrs)
+     if getChildSchema != None:
+       self.getChildSchema = getChildSchema
+ 
+   def __cmp__(self, other):
+     if not isinstance(other, Schema):
+       return 1
+     elif id(other) == id(self):
+       return 0
+     else:
+       return cmp(string.lower(self.name), string.lower(other.name)) or 1
+ 
+   def getChildSchema(self, parent):
+     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
+ 
Index: gnue-common/src/datasources/GDataSource.py
diff -c /dev/null gnue-common/src/datasources/GDataSource.py:1.64.2.1
*** /dev/null   Thu Oct  9 21:21:38 2003
--- gnue-common/src/datasources/GDataSource.py  Thu Oct  9 21:21:08 2003
***************
*** 0 ****
--- 1,579 ----
+ #
+ # 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:
+ # GDataSource.py
+ #
+ # DESCRIPTION:
+ # Class that implements a provider-independent DataSource object
+ #
+ # NOTES:
+ #
+ # HISTORY:
+ #
+ 
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GDataObjects
+ from gnue.common.definitions import GObjects
+ import sys, string, types
+ from gnue.common.datasources import GConnections
+ from gnue.common.formatting import GTypecast
+ from gnue.common.datasources import GConditions
+ 
+ ########################################################################
+ #
+ # Class that handles DataSources.  This is a subclass of GObj, which
+ # means this class can be created from XML markup and stored in an
+ # Object tree (e.g., a Forms tree).
+ #
+ ########################################################################
+ 
+ class GDataSource(GObjects.GObj):
+ 
+   def __init__(self, parent=None, type="GDataSource"):
+     GObjects.GObj.__init__(self, parent, type)
+     self.type = "object"
+     self.connection = None
+     self._connections = None
+     self._dataObject = None
+     self._connectionComment = ""
+     self._fieldReferences = {}
+     self._unboundFieldReferences = {}
+     self._defaultValues = {}
+ 
+     self._inits =[self.primaryInit, self.secondaryInit, self.tertiaryInit]
+     self._currentResultSet = None
+     self._resultSetListeners = []
+     self._toplevelParent = None # Needs to be set by subclass
+                                       # so that _topObject gets set
+     self._topObject = None
+ 
+     #
+     # trigger support
+     #
+     self._triggerGlobal = 1
+     self._triggerFunctions = 
{'createResultSet':{'function':self.createResultSet,
+                                                  },
+                               
'simpleQuery':{'function':self.triggerSimpleQuery,
+                                              },
+                               
'delete':{'function':self.deleteCurrentRecordsetEntry,
+                                         'global':1,
+                                         },
+                               
'call':{'function':self.callFuncOfCurrentRecordsetEntry,
+                                         'global':1,
+                                         },
+                               'getCondition':{'function':self.getCondition},
+                               'setCondition':{'function':self.setCondition},
+                               }
+ 
+     self._triggerProperties = {'extensions':{'get':self.getExtensions,
+                                            'direct':1}}
+ 
+   def __getattr__(self, attr):
+     if self._dataObject and attr[1] != '_' and hasattr(self._dataObject,attr):
+       return getattr(self._dataObject,attr)
+     else:
+       raise AttributeError, attr
+ 
+   def _buildObject(self):
+ 
+     # Added 0.5.0 -- Delete before 1.0
+     if hasattr(self,'database'):
+       self.connection = self.database
+       del self.database
+ 
+     try:
+       for field in string.split(self.explicitfields,','):
+         self._fieldReferences[field] = 1
+     except AttributeError:
+       pass
+     try:
+       # TODO: This might be deprecated;
+       # TODO: should be using <sorting> tags
+       for field in string.split(self.order_by,','):
+         if field[-5:].lower() == ' desc':
+           field = field[:-5]
+         self._fieldReferences[field] = 1
+     except AttributeError:
+       pass
+     return GObjects.GObj._buildObject(self)
+ 
+ 
+   def triggerSimpleQuery(self,maskDict):
+     queryDict = {}
+     okToProcess = 1
+     for key in maskDict.keys():
+       queryDict[key]= str(maskDict[key])
+       if not len(queryDict[key]):
+         okToProcess = 0
+         break
+ 
+     conditions = 
GConditions.buildConditionFromDict(queryDict,GConditions.GClike)
+     resultSet = self.createResultSet(conditions)
+     recordCount = resultSet.getRecordCount()
+ 
+     returnList = []
+     for count in range(recordCount):
+       record = resultSet.getRecord(count)
+       resultDict = {}
+       for key in record._fields.keys():
+         resultDict[key]=record.getField(key) or ""
+       returnList.append(resultDict)
+     return returnList
+ 
+   def deleteCurrentRecordsetEntry(self):
+     self._currentResultSet.getPostingRecordset().delete()
+ 
+   def callFuncOfCurrentRecordsetEntry(self,name,params):
+     n=self._currentResultSet.getRecordNumber()
+     rset=self._currentResultSet.getRecord(n)
+     if hasattr(rset,'callFunc'):
+       rset.callFunc(name,params)
+     else:
+       tmsg = _("Backend doesn't support the trigger 'call' function")
+       raise StandardError, tmsg
+ 
+   #
+   # get/set the static condition assosiated with a datasource
+   # the static condition is build out of the <condition> child
+   # elements below a datasource XML definition
+   #
+   def setCondition(self, mycondition):
+     dataObject._staticCondition = mycondition
+ #   dataObject.invalidateCachedConditions()
+ 
+   def getCondition(self):
+     return dataObject._staticCondition
+ 
+   #
+   # get the dbdriver extension object
+   #
+   def getExtensions(self):
+     return self.extensions
+ 
+   #
+   # This method should be called after the object is created
+   # but before any other methods are called
+   #
+   def setConnectionManager(self, connectionManager):
+     self._connections = connectionManager
+ 
+   def initialize(self):
+     print self.name
+     if not self.connection:
+       # We are a connectionless datasource (virtual?)
+       # We have to bind to something, so bind to empty or static driver
+       if not self.type=="static":
+         from gnue.common.datasources.drivers.special.unbound import Driver
+         GDebug.printMesg (7, 'Using empty data driver')
+         dataObject = Driver.supportedDataObjects['object'](None)
+ 
+       else:
+         from gnue.common.datasources.drivers.special.static import Driver
+         GDebug.printMesg (7, 'Using static data driver')
+         dataObject = Driver.supportedDataObjects['object'](None)
+ 
+         for child in self._children:
+           if isinstance(child, GStaticSet):
+             dataObject._staticSet = child
+             break
+ 
+ 
+     elif self._connections:
+       self.connection = string.lower(self.connection)
+       # 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)
+       dataObject = \
+          self._connections.getDataObject(self.connection, self.type)
+       GDebug.printMesg (7, "GDataSource.py bound to %s " % self._dataObject)
+ 
+     self.name = string.lower(self.name)
+     self._topObject._datasourceDictionary[self.name]=self
+ 
+     dataObject._fieldReferences = self._fieldReferences
+     dataObject._unboundFieldReferences = self._unboundFieldReferences
+     dataObject._defaultValues = self._defaultValues
+     dataObject._dataSource = self
+ 
+     # TODO: Short-term hack to allow primary key support
+     try:
+       dataObject._primaryIdField = self.primarykey
+       dataObject._primaryIdFormat = "%s = '%%s'" % self.primarykey
+       dataObject._primaryIdChecked = 1
+     except AttributeError:
+       pass
+ 
+     for child in self._children:
+       if isinstance(child, GConditions.GCondition):
+         dataObject._staticCondition = child
+         break
+ 
+     # Copy all attributes from XML to the dataObject
+     tagAttributes = getXMLelements()['datasource']['Attributes']
+     for attribute in tagAttributes.keys():
+       if self.__dict__.has_key(attribute):
+         dataObject.__dict__[attribute] = self.__dict__[attribute]
+       else:
+         try:
+           dataObject.__dict__[attribute] = tagAttributes[attribute]['Default']
+         except KeyError:
+           pass
+     self._dataObject = dataObject
+ 
+ 
+   def connect(self):
+     if self.connection != None:
+       self._connections.requestConnection(self._dataObject)
+ 
+ 
+   def getDataObject(self):
+     return self._dataObject
+ 
+ 
+   def referenceField(self, field, defaultValue=None):
+     GDebug.printMesg(7,'Field %s implicitly referenced' % field)
+     self._fieldReferences[field] = ""
+ 
+     if defaultValue != None:
+       self._defaultValues[field] = defaultValue
+ 
+   def referenceFields(self, fields):
+     for field in fields:
+       if type(field) == types.StringType:
+         self.referenceField(field)
+       else:
+         self.referenceField(*field)
+ 
+   def referenceUnboundField(self, field, defaultValue=None):
+     GDebug.printMesg(7,'Field %s implicitly referenced' % field)
+     self._unboundFieldReferences[field] = 1
+ 
+     if defaultValue != None:
+       self._defaultValues[field] = defaultValue
+ 
+ 
+   #
+   # The following are a simple wrapper around the datasource's dataobject
+   # to hide the dataobject from the app programmer
+   #
+   def hasMaster(self):
+     return self._dataObject != None and self._dataObject.hasMaster()
+ 
+   def createResultSet(self, conditions={}, readOnly=0, sql=""):
+       resultSet= self._dataObject.createResultSet(conditions,readOnly,sql=sql)
+       self.__setResultSet( resultSet )
+       return resultSet
+ 
+   def addDetailDataObject(self, dataObject, handler=None):
+       self._dataObject.addDetailDataObject(dataObject, handler)
+ 
+   def createEmptyResultSet(self, readOnly=0,masterRecordSet=None):
+       resultSet = self._dataObject.createEmptyResultSet(readOnly, 
masterRecordSet=masterRecordSet)
+       self.__setResultSet( resultSet )
+       return resultSet
+ 
+   def getQueryString(self,conditions={},forDetailSQL=None,additionalSQL=""):
+     return self._dataObject.getQueryString(conditions, 
forDetailSQL,additionalSQL)
+ 
+   #
+   # Master/detail stuff
+   #
+ 
+   # Called by dbdrivers whenever this datasource's master has changed
+   def masterResultSetChanged(self, masterResultSet, detailResultSet):
+     self._masterResultSet = masterResultSet
+     self.__setResultSet( detailResultSet )
+ 
+   def __setResultSet(self, resultSet):
+     self._currentResultSet = resultSet
+     # Notify all the listeners (i.e., blocks) that the result set changed
+     for listener in self._resultSetListeners:
+       listener(resultSet)
+ 
+   def registerResultSetListener(self, listener):
+     self._resultSetListeners.append(listener)
+ 
+   def primaryInit(self):
+     self._topObject = self.findParentOfType(self._toplevelParent)
+     GDebug.printMesg(10,"Setting %s to connect mgr %s" 
%(self.name,self._topObject._connections))
+     self.setConnectionManager(self._topObject._connections)
+     self.initialize()
+     self.connect()
+     self.extensions = self._dataObject.triggerExtensions    
+ 
+   # TODO: Merged into GDataSource per the TODOs in reports and forms however
+   # TODO: self._topObject._datasourceDictionary implies that the top object
+   # TODO: always has a specifc structure.  This is a bad thing :(  Maybe 
GRootObj
+   # TODO: should contain a getDatasourceDict()?
+   #
+   def secondaryInit(self):
+ 
+     if hasattr(self, 'master') and self.master:
+ 
+       self.master = string.lower(self.master)
+       GDebug.printMesg(3,"Linking detail '%s' to master '%s'" \
+                          % (self.name, self.master) )
+ 
+       if self._topObject._datasourceDictionary.has_key(self.master):
+         self._topObject._datasourceDictionary[self.master] \
+             .getDataObject().addDetailDataObject(self.getDataObject(),
+                                                  self)
+       else:
+         tmsg = _("Detail source '%s' references non-existant master '%s'") \
+                          % (self.name, self.master)
+         raise StandardError, tmsg
+ 
+   def tertiaryInit(self):
+     if hasattr(self, 'prequery'):
+       if not self.hasMaster() and self.prequery:
+         self.createResultSet()
+ 
+   #
+   # Hooks for record-level triggers
+   #
+ 
+   def _beforeCommitInsert(self, record):
+     return 1
+ 
+   def _beforeCommitUpdate(self, record):
+     return 1
+ 
+   def _beforeCommitDelete(self, record):
+     return 1
+ 
+   def _onModification(self, record):
+     return 1
+ 
+   def _onRecordLoaded(self, record):
+     return 1
+ 
+ 
+ 
+ ######
+ #
+ #
+ #
+ ######
+ class GSql(GObjects.GObj):
+   def __init__(self, parent=None):
+      GObjects.GObj.__init__(self, parent, type="GDSql")
+ 
+ ######
+ #
+ # Static Datasource Support
+ #
+ ######
+ class GStaticSet(GObjects.GObj):
+   def __init__(self, parent=None):
+      GObjects.GObj.__init__(self, parent, type="GDStaticSet")
+ 
+ class GStaticSetRow(GObjects.GObj):
+   def __init__(self, parent=None):
+      GObjects.GObj.__init__(self, parent, type="GDStaticSetRow")
+ 
+ class GStaticSetField(GObjects.GObj):
+   def __init__(self, parent=None):
+      GObjects.GObj.__init__(self, parent, type="GDStaticSetField")
+ 
+ 
+ ######
+ #
+ #
+ #
+ ######
+ class GConnection(GObjects.GObj):
+   def __init__(self, parent=None):
+     GObjects.GObj.__init__(self, parent, "GCConnection")
+     self.comment = ""
+     self.name = ""
+     self._inits =[self.initialize]
+ 
+   def _buildObject(self):
+     self.name = string.lower(self.name)
+     return GObjects.GObj._buildObject(self)
+ 
+   def initialize(self):
+     # Add our database connection information to the connections
+     # manager, then let it handle everything from there.
+     root = self.findParentOfType(None)
+     root._instance.connections.\
+         addConnectionSpecification(self.name, {
+            'name': self.name,
+            'provider': self.provider,
+            'dbname': self.dbname,
+            'host': self.host } )
+ 
+ 
+ 
+ ######
+ #
+ # Used by client GParsers to automatically pull supported xml tags
+ #
+ ######
+ 
+ #
+ # Return any XML elements associated with
+ # GDataSources.  Bases is a dictionary of tags
+ # whose values are update dictionaries.
+ # For example: bases={'datasource': {'BaseClass':myDataSource}}
+ # sets xmlElements['datasource']['BaseClass'] = myDataSource
+ #
+ def getXMLelements(updates={}):
+ 
+   xmlElements = {
+       'datasource': {
+          'BaseClass': GDataSource,
+          'Importable': 1,
+          'Attributes': {
+             'name':        {
+                'Required': 1,
+                'Unique':   1,
+                'Typecast': GTypecast.name },
+             'type':        {
+                'Typecast': GTypecast.name,
+                'Default':  "object" },
+             'connection':    {
+                'Typecast': GTypecast.name },
+             'database':    {
+                'Typecast': GTypecast.name, 
+                'Deprecated': 'Use {connection} attribute instead' },
+             'table':       {
+                'Typecast': GTypecast.name },
+             'cache':       {
+                'Typecast': GTypecast.whole,
+                'Default':  5 },
+             'prequery':    {
+                'Typecast': GTypecast.boolean,
+                'Default':  0 },
+             'distinct':    {
+                'Typecast': GTypecast.boolean,
+                'Default':  0 },
+             'order_by':    {
+                'Typecast': GTypecast.text },
+             'master':      {
+                'Typecast': GTypecast.name },
+             'masterlink':  {
+                'Typecast': GTypecast.text },
+             'detaillink':  {
+                'Typecast': GTypecast.text },
+             # TODO: Short-term hack
+             'explicitfields': {
+                'Typecast': GTypecast.text },
+             'primarykey': {
+                'Typecast': GTypecast.text } },
+          'ParentTags': None },
+       'staticset': {
+          'BaseClass': GStaticSet,
+ #  TODO: This should be replaced by a SingleInstanceInParentObject
+ #        instead of SingleInstance (in the whole file)
+ #         'SingleInstance': 1,
+          'Attributes': {
+             'fields':        {
+                'Typecast': GTypecast.text,
+                'Required': 1 } },
+          'ParentTags': ('datasource',) },
+       'staticsetrow': {
+          'BaseClass': GStaticSetRow,
+          'ParentTags': ('staticset',) },
+       'staticsetfield': {
+          'BaseClass': GStaticSetField,
+          'Attributes': {
+             'name':        {
+                'Typecast': GTypecast.text,
+                'Required': 1 },
+             'value':        {
+                'Typecast': GTypecast.text,
+                'Required': 1 } },
+          'ParentTags': ('staticsetrow',) },
+       'connection': {
+          'BaseClass': GConnection,
+          'Attributes': {
+             'name': {
+                'Required': 1,
+                'Unique': 1,
+                'Typecast': GTypecast.name,
+                'Description': 'TODO' },
+             'provider': {
+                'Required': 1,
+                'Typecast': GTypecast.name,
+                'Description': 'TODO' },
+             'dbname': {
+                'Required': 0,
+                'Typecast': GTypecast.text,
+                'Description': 'TODO' },
+             'service': {
+                'Required': 0,
+                'Typecast': GTypecast.text,
+                'Description': 'TODO' },
+             'comment': {
+                'Required': 0,
+                'Typecast': GTypecast.text,
+                'Description': 'TODO' },
+             'host': {
+                'Required': 0,
+                'Typecast': GTypecast.text,
+                'Description': 'TODO' } },
+          'ParentTags': None,
+          'Description': 'TODO' },
+   }
+ 
+   # Add conditional elements
+   xmlElements.update(
+       GConditions.getXMLelements(
+           {'condition':{'ParentTags':('datasource',) } } ))
+ 
+   for alteration in updates.keys():
+     xmlElements[alteration].update(updates[alteration])
+ 
+   # Connections will have the same parent as datasources
+   xmlElements['connection']['ParentTags'] = 
xmlElements['datasource']['ParentTags']
+ 
+   return xmlElements
+ 
+ 
+ #
+ # Wrapper for standalone DataSources
+ # (i.e., not in context of a GObj tree)
+ #
+ def DataSourceWrapper(connections=None, fields=(), attributes={}, init=1):
+   source = _DataSourceWrapper()
+   
+   if connections: 
+     source.setConnectionManager(connections)
+   
+   if init: 
+     source.buildAndInitObject(**attributes)
+   else: 
+     source.buildObject(**attributes)
+     
+   if fields: 
+     source.referenceFields(fields)
+   
+   return source
+   
+   
+ class _DataSourceWrapper(GDataSource): 
+   def __init__(self, *args, **parms): 
+     GDataSource.__init__(self, *args, **parms)
+     self._datasourceDictionary={}
+     self._toplevelParent = self._type
+     
+ 
Index: gnue-common/src/datasources/GIntrospection.py
diff -c /dev/null gnue-common/src/datasources/GIntrospection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:39 2003
--- gnue-common/src/datasources/GIntrospection.py       Thu Oct  9 21:21:09 2003
***************
*** 0 ****
--- 1,66 ----
+ #
+ # 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:
+ #   Old methods in GDataObjects and their new counterparts:
+ #     * getSchemaTypes()       -->  types
+ #     * getSchemaList()        -->  find(type='...')
+ #     * getSchemaByName()      -->  find(name='...')
+ #     * writeSchema()          -->  write()
+ #
+ #  Preferred way to access these discovery routines is:
+ #    connection.schema.<function>
+ #
+ 
+ 
+ 
+ 
+ #
+ # Schema (metadata) functions
+ #
+ class Introspection:
+ 
+   # Return a list of the types of Schema objects this driver provides
+   # Contains tuples of (key, description, dataSource??)
+   # dataSource?? is true if this schema type can be a datasource
+   types = []
+ 
+ 
+   # Return a list of Schema objects
+   def find(self, name=None, type=None):
+     return []
+ 
+ 
+   def findfirst(self, *args, **parms):
+     return self.find(*args, **parms)[0]
+ 
+ 
+   # write Schema to Database
+   def write(self,obj,overwrite=0):
+     tmsg = _("This database adapter doesn't have 'schema writing' support")
+     raise NoWriteSchemaSupport, tmsg
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/DBSIG2/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/DBSIG2/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:39 2003
--- gnue-common/src/datasources/drivers/DBSIG2/Connection.py    Thu Oct  9 
21:21:09 2003
***************
*** 0 ****
--- 1,72 ----
+ #
+ # 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:
+ #
+ 
+ __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):
+     return [['_username', _('User Name'),0],['_password', _('Password'),1]]
+ 
+   def commit(self):
+     GDebug.printMesg (5,"DB-SIG database driver: commit()")
+ 
+     try:
+       self.native.commit()
+     except self._DatabaseError, value:
+       raise GDataObjects.ConnectionError, value
+ 
+     self._beginTransaction()
+ 
+   def rollback(self):
+     GDebug.printMesg (5,"DB-SIG database driver: rollback()")
+ 
+     try:
+       self.native.rollback()
+     except:
+       pass    # I'm SURE this isn't right (jcater)
+                 # But not all db's support transactions
+ 
+     self._beginTransaction()
+ 
+ 
+   # 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
Index: gnue-common/src/datasources/drivers/DBSIG2/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/DBSIG2/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:39 2003
--- gnue-common/src/datasources/drivers/DBSIG2/DataObject.py    Thu Oct  9 
21:21:09 2003
***************
*** 0 ****
--- 1,324 ----
+ #
+ # 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:
+ # DBSIG2/DataObject.py
+ #
+ # DESCRIPTION:
+ # Generic implementation of dbdriver using Python DB-SIG v2
+ # specification.
+ #
+ # NOTES:
+ # The classes below are meant to be extended
+ #
+ # HISTORY:
+ #
+ 
+ __all__ = ['DataObject','DataObject_SQL','DataObject_Object']
+ 
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ import string
+ import types
+ 
+ from ResultSet import ResultSet
+ 
+ ######################################################################
+ #
+ #
+ #
+ class DataObject(GDataObjects.DataObject):
+ 
+   _escapeSingleQuote = "'"
+   _resultSetClass = ResultSet
+   _DatabaseError = None
+ 
+   # The date/time format used in insert/select statements
+   # (based on format used for time.strftime())
+   _dateTimeFormat = "'%c'"
+ 
+   # 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
+   _primaryIdField = None         # Internal recordset field name 
(lowercase!!!)
+   _primaryIdSelect = ""  # Select clause
+   _primaryIdFormat = "__gnue__ = '%s'"         # Where clause format
+ 
+   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      )}
+ 
+ 
+   def __init__(self, *args, **params):
+     GDataObjects.DataObject.__init__(self, *args, **params)
+ 
+     GDebug.printMesg (1,"DB-SIG database driver backend initializing")
+ 
+ 
+     # TODO: uh, hmm..
+     self._strictQueryCount = 1   # strictQueryCount
+ 
+     self.distinct = 0
+ 
+     # Internal flag to avoid consistently doing the same check
+     # If this is set to 1 initially, then the
+     self._primaryIdChecked = 1  # Internal flag
+ 
+ 
+ 
+   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)
+ 
+ 
+   # 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._connection.native.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._connection.native.cursor()
+ 
+     cursor.execute(self._buildQueryCount(conditions,additionalSQL=sql))
+     rs = cursor.fetchone()
+     return int(rs[0])
+ 
+ 
+   # 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
+ 
+ 
+ 
+ ######################################################################
+ #
+ #
+ #
+ class DataObject_Object(DataObject):
+ 
+   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 DataObject_SQL(DataObject):
+   def _buildQuery(self, conditions={}):
+     # Obviously, this is in a pre-alpha state :)
+     return "select zipcode, city, state from zipcode order by zipcode desc"
+ 
+ 
Index: gnue-common/src/datasources/drivers/DBSIG2/Driver.py
diff -c /dev/null gnue-common/src/datasources/drivers/DBSIG2/Driver.py:1.76.2.1
*** /dev/null   Thu Oct  9 21:21:39 2003
--- gnue-common/src/datasources/drivers/DBSIG2/Driver.py        Thu Oct  9 
21:21:09 2003
***************
*** 0 ****
--- 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
+ }
+ 
+ 
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:39 2003
--- gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py     Thu Oct  9 
21:21:10 2003
***************
*** 0 ****
--- 1,134 ----
+ #
+ # 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
+ #
+ 
+ __all__ = ['RecordSet']
+ 
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ import string
+ import types
+ 
+ 
+ ######################################################################
+ #
+ #
+ #
+ class 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 ') )
+ 
Index: gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:40 2003
--- gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py     Thu Oct  9 
21:21:10 2003
***************
*** 0 ****
--- 1,88 ----
+ #
+ # 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:
+ #
+ 
+ __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:
+       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
+ 
Index: gnue-common/src/datasources/drivers/DBSIG2/__init__.py
diff -c /dev/null gnue-common/src/datasources/drivers/DBSIG2/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:40 2003
--- gnue-common/src/datasources/drivers/DBSIG2/__init__.py      Thu Oct  9 
21:21:10 2003
***************
*** 0 ****
--- 1,25 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ from DataObject import *
+ from ResultSet import *
+ from RecordSet import *
Index: 
gnue-common/src/datasources/drivers/adodbapi/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/adodbapi/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:40 2003
--- 
gnue-common/src/datasources/drivers/adodbapi/Schema/Discovery/Introspection.py  
    Thu Oct  9 21:21:11 2003
***************
*** 0 ****
--- 1,141 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('view',_('Views'),1),
+            ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     QueryType = adSchemaTables
+     rs = self.adoConn.OpenSchema(QueryType)
+ 
+     rs.MoveFirst()
+     tables = []
+     while not rs.EOF:
+       if str(rs.Fields(TABLE_TYPE)) == 'TABLE':
+         tables.append((str(rs.Fields(TABLE_NAME)),'table'))
+       elif str(rs.Fields(TABLE_TYPE)) == 'VIEW':
+         tables.append((str(rs.Fields(TABLE_NAME)),'view'))
+       rs.MoveNext()
+ 
+     list = []
+     for t in tables:
+       list.append(GDataObjects.Schema(attrs={'id':t[0], 'name':t[0],
+                          'type':t[1],
+                        'primarykey': self.__getPrimaryKey(t[0])},
+                          getChildSchema=self.__getFieldSchema))
+     return list
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     schema = GDataObjects.Schema(attrs={'id':name, 'name':name,
+                          'type':'table',
+                        'primarykey': self.__getPrimaryKey(name)},
+                          getChildSchema=self.__getFieldSchema)
+     return schema
+ 
+   # Return a list of fields (for _buildDeleteStatement and for 
_buildUpdateStatement)
+   def __getPrimaryKey(self, relname):
+     # TODO
+     return []
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+     statement = "select * from %s where 0=1" % (parent.name)
+ 
+     cursor = self.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+ 
+     for d in cursor.description:
+       try:
+         nativetype = d[DESCRIPTION_TYPE_CODE]
+       except AttributeError:
+         nativetype='unknown'
+ 
+       attrs={'id':d[DESCRIPTION_NAME],
+                  'name':d[DESCRIPTION_NAME],
+                  'type':'field',
+                  'nativetype': nativetype,
+                  'required': d[DESCRIPTION_NULL_OK]==0,
+                  'length': d[DESCRIPTION_INTERNAL_SIZE]}
+ 
+       if nativetype == SIG2api.NUMBER:
+         attrs['datatype']='number'
+         attrs['precision']=d[DESCRIPTION_SCALE]
+         attrs['length']=d[DESCRIPTION_PRECISION]
+       elif nativetype == SIG2api.DATETIME:
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+ 
Index: gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:40 2003
--- gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py Thu Oct 
 9 21:21:11 2003
***************
*** 0 ****
--- 1,84 ----
+ #
+ # 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:
+ # adodbapi/Connection.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via adodbapi Driver
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Connection']
+ 
+ 
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ from DataObject import *
+ from gnue.common.datasources.drivers.adodbapi.Schema.Discovery.Introspection 
import Introspection
+ 
+ try:
+   import adodbapi as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: adodbapi driver\n\n[%s") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ try:
+   import win32com
+ except ImportError, message:
+   tmsg = _("Driver not installed: win32com driver\n\n[%s") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Connection(DBSIG2.Connection):
+   _defaultBehavior = Introspection
+   _DatabaseError = SIG2api.DatabaseError
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Adodbapi database driver initializing")
+ 
+     try:
+       connPar = {'Provider': connectData['oledb_provider'],
+                       'Data Source' : connectData['data_source'],
+                       'User Id' : connectData['_username'],
+                       'Password' : connectData['_password']
+                      }
+       # optional parameters for MS SQL Server
+       for gnueName, oledbName in [('initial_catalog', 'Initial Catalog'),
+                                               ('network_library', 'Network 
Library'),
+                                               ('data_provider', 'Data 
Provider'),
+                                               ]:
+           if connectData.has_key(gnueName):
+               connPar[oledbName] = connectData[gnueName]
+ 
+       connStr = ';'.join([r"%s=%s" % (k,v) for k,v in connPar.items()])
+       GDebug.printMesg(1,'Adodbapi connection string="%s"' % connStr)
+ 
+       self.native = SIG2api.connect(connStr)
+ 
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
Index: gnue-common/src/datasources/drivers/adodbapi/adodbapi/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/adodbapi/adodbapi/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:41 2003
--- gnue-common/src/datasources/drivers/adodbapi/adodbapi/DataObject.py Thu Oct 
 9 21:21:11 2003
***************
*** 0 ****
--- 1,70 ----
+ #
+ # 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:
+ # adodbapi/DataObject.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via adodbapi Driver
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['DataObject']
+ 
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ 
+ 
+ class DataObject_Object(DBSIG2.DataObject_Object):
+ 
+   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:
+ #        #disable the count query and see if anyone screams
+ #        recordCount = cursor.rowcount
+ 
+         #adodbapi 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
+ 
+ DataObject_SQL = DBSIG2.DataObject_SQL
Index: gnue-common/src/datasources/drivers/adodbapi/adodbapi/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/adodbapi/adodbapi/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:41 2003
--- gnue-common/src/datasources/drivers/adodbapi/adodbapi/__init__.py   Thu Oct 
 9 21:21:11 2003
***************
*** 0 ****
--- 1,54 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("ADO-DB Data Driver for MS SQL-Server/Access")
+ __driverurl__ = "http://sourceforge.net/projects/adodbapi";
+ 
+ __doc__ = _("""
+    Supported attributes (via connections.conf or <database> tag)""") + """
+ 
+      oledb_provider   (required)
+      data_source      (required)
+      initial_catalog   (optional for SQL Server)
+      network_library (optional for SQL Server)
+      data_provider    (optional for SQL Server)""" + _("""
+ 
+  You can find more connection strings here:""") + """
+  http://www.able-consulting.com/MDAC/ADO/Connection/OLEDB_Providers.htm
+ """
+ 
+ __examples__ = """
+ [access]
+ comment = """ + _("MS Access database") + """
+ provider = adodbapi
+ oledb_provider = Microsoft.Jet.OLEDB.4.0
+ data_source = C:\mydb.mdb
+ 
+ [sqlserver]
+ comment = """ + _("MS SQL Server database") + """
+ provider = adodbapi
+ oledb_provider = sqloledb
+ data_source = myServerName
+ initial_catalog = myDatabaseName
+ """
+ 
Index: 
gnue-common/src/datasources/drivers/appserver/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/appserver/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:41 2003
--- 
gnue-common/src/datasources/drivers/appserver/Schema/Discovery/Introspection.py 
    Thu Oct  9 21:21:12 2003
***************
*** 0 ****
--- 1,168 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types = [('object',_('Business Object Class'),1)]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   #############
+   #
+   #  get list of all business classes
+   #
+   # TODO: Merge into find()
+   #
+   def getSchemaList(self, type=None):
+       if not(type in ('object',None)):
+         return []
+ 
+       try:
+         listcursor = 
self._connection.request('gnue_class',[],['gnue_module'],['gnue_name','gnue_comment','gnue_module'])
+       except Exception, msg:
+         print "error %s" %msg
+         GDebug.printMesg(1,_("Error creating introspection module list \n\n 
--- %s ---)") % msg)
+         return []
+ 
+       list = []
+       data = ['1']
+       while len(data):
+         data = listcursor.fetch()
+         for classdef in data:
+           print classdef
+           schema = 
GDataObjects.Schema(attrs={'id':string.lower(classdef['gnue_name']),
+                                               'name':classdef['gnue_name'],
+                                               'type':'object',
+                                               'gnue_id':classdef['gnue_id']},
+                                        getChildSchema=self.__getChildSchema)
+           list.append(schema)
+ 
+ 
+       listcursor.close()
+ 
+       return list
+ 
+   #############
+   #
+   #  get schema for one single business class
+   #
+   # TODO: Merge into find()
+   #
+   def getSchemaByName(self, name, type=None):
+       try:
+         listcursor = self._connection.request('gnue_class', [["eq", ""], 
["field", "gnue_name"], ["const", name]],
+                                                   
['gnue_module'],['gnue_name','gnue_comment','gnue_module'])
+       except Exception, msg:
+         print "error %s" %msg
+         GDebug.printMesg(1,_("Error fetching class %s \n\n --- %s ---)") % 
(name,msg))
+         return []
+ 
+       data = listcursor.fetch()
+       if len(data):
+         classdef = data[0]
+         print classdef
+         schema = 
GDataObjects.Schema(attrs={'id':string.lower(classdef['gnue_name']),
+                                             'name':classdef['gnue_name'],
+                                             'type':'object',
+                                             'gnue_id':classdef['gnue_id']},
+                                      getChildSchema=self.__getChildSchema)
+       listcursor.close()
+ 
+       return schema
+ 
+ 
+   #############
+   #
+   #  get schema for one single business class
+   #
+ 
+   def __getChildSchema(self, parent):
+       try:
+         # fetch all properties used by class "parent"
+         listcursor = self._connection.request('gnue_property',  # class
+                                                   [["eq", ""], ["field", 
"gnue_class"],
+                                                                ["const", 
parent.gnue_id]], # condition
+                                                   ['gnue_module'],  # sort
+                                                   
['gnue_name','gnue_comment','gnue_module','gnue_class','gnue_type',
+                                                    
'gnue_length','gnue_scale'])
+ 
+       except Exception, msg:
+         print "error %s" %msg
+         GDebug.printMesg(1,_("Error while loading class properties for class 
%s \n\n --- %s ---)") % (parent.name,msg))
+         return []
+ 
+       list = []
+       data = ['1']
+       while len(data):
+         data = listcursor.fetch()
+         for propdef in data:
+           print propdef
+           attrs={'id': "%s.%s" % (parent.id, 
string.lower(propdef['gnue_name'])),
+                  'name': propdef['gnue_name'],
+                  'precision': propdef['gnue_scale'],   # TODO: check if scale 
and precision is the same
+                  'datatype':propdef['gnue_type'],
+                  'nativetype': 'unknown',
+                  'required': 0 }                       # TODO: classrep has 
no  'required' field
+ 
+           # TODO: make classrep types a bit more straigtforward
+           if propdef['gnue_type'] =='id' or propdef['gnue_type'] 
=='gnue_module' \
+                  or propdef['gnue_type'] =='gnue_class':
+             attrs['length'] =  32
+           else:
+             attrs['length'] =  propdef['gnue_length']
+ 
+           list.append(GDataObjects.Schema(attrs=attrs))
+ 
+       listcursor.close()
+ 
+       return list
Index: gnue-common/src/datasources/drivers/appserver/appserver/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/appserver/appserver/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:41 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/Connection.py       
Thu Oct  9 21:21:12 2003
***************
*** 0 ****
--- 1,228 ----
+ #
+ # 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:
+ # appserver/Connection.py
+ #
+ # DESCRIPTION:
+ # Implementation of dbdriver for use with GNUe Application Server.
+ #
+ # NOTES:
+ #
+ # HISTORY:
+ #
+ 
+ VERSION="0.0.1"
+ 
+ __all__ = ['Connection']
+ 
+ from gnue.common.datasources import GDataObjects, GConditions, GConnection
+ from gnue.common.apps import GDebug
+ from gnue.common.rpc import GComm
+ 
+ from DataObject import *
+ 
+ import string
+ import types
+ import md5
+ import sys
+ 
+ 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
+   }
+ 
+   # We only need the basics -- username and password -- to log in
+   def getLoginFields(self):
+     return [['_username', 'User Name',0],['_password', 'Password',1]]
+ 
+   def connect(self):
+ 
+     user = connectData['_username']
+     passwd = connectData['_password']
+ 
+     params = { 'host': connectData['host'],
+                'port': connectData['port'],
+                'transport': connectData['transport']}
+ 
+     self._server = GComm.attach(connectData['rpctype'],params)
+ 
+     GDebug.printMesg(3,"Setup the link to the session manager")
+     self._sm = self._server.request("Session")
+ 
+     #GDebug.printMesg(3,"Get the status of the session manager")
+     #GDebug.printMesg(3,"Status: "+sessionManager.Status())
+ 
+     try:
+       GDebug.printMesg(3,"Open Session ...")
+       GDebug.printMesg(1,"Logging into appserver as user '%s'" % (user))
+       self._sess_id = self._sm.open({'user':user,'password':passwd})
+     except Exception,msg:
+       tmsg = _("Error loging into appserver: %s") % msg
+       raise GDataObjects.ConnectionError, tmsg
+ 
+     if self._sess_id == 0:
+       tmsg = _("Error loging into appserver")
+       raise GDataObjects.ConnectionError, tmsg
+ 
+     self._updateCursor = Appserver_UpdateCursor(self)
+ 
+   def cursor(self):
+     return self._updateCursor
+ 
+   def request(self,table,filter,sort,fieldlist):
+     listid = self._sm.request(self._sess_id,table,filter,sort,fieldlist)
+     return Appserver_ListCursor(self,listid,fieldlist)
+ 
+   def call(self,classname,obj_id_list,methodname,parameters):
+     self._sm.call(self._sess_id,classname,obj_id_list,methodname,parameters)
+ 
+   def commit(self,classname):
+     self._updateCursor.execute(classname)
+     self._sm.commit(self._sess_id)
+ 
+   def rollback(self,classname):
+     self._updateCursor.revert(classname)
+     self._sm.rollback(self._sess_id)
+ 
+   def close(self,commit):
+     self._sm.close(self._sess_id,commit)
+ 
+   # Return a sequence number from sequence 'name'
+   # def getSequence(self, name):
+   # !!! has to be emulated !!!
+   # return self.__singleQuery("select nextval('%s')" % name)
+ 
+   # Run the SQL statement 'statement'
+   #def sql(self, statement):
+   # !!! has to be emulated !!!
+   #  cursor = self.__connection.cursor()
+   #  try:
+   #    cursor.execute(statement)
+   #    cursor.close()
+   #  except:
+   #    cursor.close()
+   #    raise
+ 
+ 
+ 
+ class Appserver_ListCursor:
+   def __init__(self,dataCon,listid,fieldlist):
+     self._dataCon=dataCon
+     self._listid=listid
+     self._fieldlist=fieldlist
+     self._stackpos=0
+ 
+   def fetch(self,count=5):
+     if self._stackpos == -1:
+       return []
+ 
+     result = self._dataCon._sm.fetch(self._dataCon._sess_id,
+                                      self._listid,self._stackpos,count)
+     if len(result)<count:
+       self._stackpos=-1
+ 
+     else:
+       self._stackpos=self._stackpos+len(result)
+ 
+     list = []
+     for i in result:
+       # xmlrpc GNURPC driver changes None into 1
+       # so we have to check for None or 1
+       # while (Instance!=None) and (Instance!=1):
+       dict = {}
+       j = 1
+       for fieldName in self._fieldlist:
+         dict[fieldName] = i[j]
+         j=j+1
+ 
+       dict["gnue_id"]=i[0]
+       list.append(dict)
+     return list
+ 
+   def count(self):
+     if not hasattr(self,"_count"):
+       self._count = 
self._dataCon._sm.count(self._dataCon._sess_id,self._listid)
+ 
+     return self._count
+ 
+   def close(self):
+     pass
+     # TODO: Implement List Close command
+ 
+ 
+ class Appserver_UpdateCursor:
+   def __init__(self,dataCon):
+     self._dataCon=dataCon
+     self._deleteList={}
+     self._updateList={}
+     self._updateKeyList={}
+ 
+   def delete(self,classname,id):
+     if not self._deleteList.has_key(classname):
+        self._deleteList[classname]=[]
+ 
+     self._deleteList[classname].append(id)
+ 
+   def update(self, classname, id, fieldDict):
+     if not self._updateList.has_key(classname):
+        self._updateList[classname]=[]
+        self._updateKeyList[classname]=[]
+     self._updateList[classname].append(fieldDict)
+     self._updateKeyList[classname].append(id)
+ 
+   def execute(self,classname):
+     #try:
+       if self._deleteList.has_key(classname): 
+         result = self._dataCon._sm.delete(self._dataCon._sess_id,classname,
+                                         self._deleteList[classname])
+       
+         self._deleteList[classname]=[]
+ 
+     #except:
+     #  return
+ 
+    # try:
+       while len(self._updateList[classname]):
+         id = self._updateKeyList[classname].pop()
+         dict = self._updateList[classname].pop()
+         # TODO: merge calls with similar updated fields (=dict.values())
+         result = 
self._dataCon._sm.store(self._dataCon._sess_id,classname,[id],
+                                          dict.keys(),[dict.values()])
+ 
+       self._updateList[classname]=[]
+       self._updateKeyList[classname]=[]
+ 
+     #except:
+     #  return
+     
+   def revert(self,classname):
+     if self._deleteList.has_key(classname):
+       self._deleteList[classname]=[]
+     if self._updateList.has_key(classname):
+       self._updateList[classname]=[]
+       self._updateKeyList[classname]=[] 
+ 
Index: gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:41 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py       
Thu Oct  9 21:21:12 2003
***************
*** 0 ****
--- 1,110 ----
+ #
+ # 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:
+ # appserver/DataObject.py
+ #
+ # DESCRIPTION:
+ # Implementation of dbdriver for use with GNUe Application Server.
+ #
+ # NOTES:
+ #
+ # HISTORY:
+ #
+ 
+ __all__ = ['DataObject']
+ 
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.rpc import GComm
+ 
+ import string
+ import types
+ import md5
+ import sys
+ 
+ from ResultSet import *
+ 
+ class DataObject(GDataObjects.DataObject):
+ 
+   _resultSetClass = ResultSet
+ 
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     # Standardize incomming conditions as a GConditions structre
+     if type(conditions) == types.DictType:
+         cond = GConditions.buildConditionFromDict(conditions)
+     else:
+         cond = conditions
+ 
+     # Construct query object
+     GDebug.printMesg(7,'Implicit Fields: %s' % self._fieldReferences)
+     query = []
+ 
+     # Add conditionals
+     query = GConditions.buildPrefixFromTree(cond._children[0] )
+ 
+     GDebug.printMesg(7,'Full query in prefix notation: %s' % query)
+ 
+     return query
+ 
+ 
+   def _createEmptyResultSet(self, readOnly=0, masterRecordSet=None):
+     return self.createResultSet(readOnly=readOnly,\
+                                 conditions=GConditions.GCimpossible,\
+                                 masterRecordSet=masterRecordSet)
+ 
+   def _createResultSet(self, conditions={}, readOnly=0,
+                        masterRecordSet=None, sql=""):
+ 
+     GDebug.printMesg (5,"Setting up list object ...");
+ 
+     sort=[]
+     filter=[]
+ 
+     # the fieldnames seem to be stored in _fieldReferences
+     fieldlist=self._fieldReferences.keys()
+     
+     GDebug.printMesg (5,"Using "+str(fieldlist)+" as fieldlist");
+     
+     if hasattr(self,"order_by"):
+       GDebug.printMesg (5,"Sorting list by fields '"+self.order_by+"'");
+       sort=string.splitfields(self.order_by,",")
+ 
+     try:
+       if conditions:
+         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)
+     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)
+     
+     if readOnly: 
+       rs._readonly = readOnly
+       
+     return rs
+ 
Index: gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:42 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py        
Thu Oct  9 21:21:12 2003
***************
*** 0 ****
--- 1,78 ----
+ #
+ # 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:
+ # appserver/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Implementation of dbdriver for use with GNUe Application Server.
+ #
+ # NOTES:
+ #
+ # HISTORY:
+ #
+ 
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.rpc import GComm
+ 
+ import string
+ import types
+ import md5
+ import sys
+ 
+ class RecordSet(GDataObjects.RecordSet):
+   def _postChanges(self):
+     if self._deleteFlag:
+       GDebug.printMesg(5, 'AppServer database driver: Instance deleted')
+       self._parent._update_cursor.delete(self._parent._dataObject.table,
+                                          self._fields["gnue_id"])
+ 
+     if self._insertFlag:
+       GDebug.printMesg(5, 'AppServer database driver: new Instance '+\
+                        'created and inserted')
+       ## Set __id__ to "0" for new instances
+       self._parent._update_cursor.update(self._parent._dataObject.table,
+                                          0, self._fields)
+ 
+     elif self._updateFlag:
+       modifiedFields={}
+       for field in (self._modifiedFlags.keys()):
+         modifiedFields[field]=self._fields[field]
+ 
+       self._parent._update_cursor.update(self._parent._dataObject.table,
+                                          self._fields["gnue_id"], 
modifiedFields)
+ 
+     self._updateFlag = 0
+     self._insertFlag = 0
+     self._deleteFlag = 0
+ 
+   # this function calls a per entry function on server side
+   def callFunc(self,name,params):
+     if self._insertFlag:
+       # store record on server
+       GDebug.printMesg(0, 'FIXME: record has to be stored on appserver '+\
+                        'and its gnue_id should be returned')
+       return
+ 
+     
self._parent._dataObject._dataConnection.call(self._parent._dataObject.table,
+                                                   [self._fields["gnue_id"]],
+                                                   name,params)
+ 
Index: gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:42 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py        
Thu Oct  9 21:21:12 2003
***************
*** 0 ****
--- 1,73 ----
+ #
+ # 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:
+ # appserver/ResultSet.py
+ #
+ # DESCRIPTION:
+ # Implementation of dbdriver for use with GNUe Application Server.
+ #
+ # NOTES:
+ #
+ # HISTORY:
+ #
+ 
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.rpc import GComm
+ 
+ import string
+ import types
+ import md5
+ import sys
+ 
+ from RecordSet import *
+ 
+ #
+ # Notes:
+ # In the Appserver driver a CURSOR is simply the List handle returned
+ # via the query interface
+ #
+ class ResultSet(GDataObjects.ResultSet):
+ 
+   _recordSetClass = RecordSet
+ 
+   def _loadNextRecord(self):
+ 
+     more = 0
+     if self._cursor:
+ 
+       # load next records into local cache
+ 
+       instances=self._cursor.fetch()
+       for i in instances:
+ 
+         more = 1
+ 
+         record=self._recordSetClass(parent=self,initialData=i)
+ 
+         self._cachedRecords.append (record)
+ 
+         self._recordCount=self._recordCount+1
+ 
+     # if no record returned return a zero
+     return more
+ 
+ 
Index: gnue-common/src/datasources/drivers/appserver/appserver/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/appserver/appserver/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:42 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/__init__.py Thu Oct 
 9 21:21:12 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("GNUe AppServer Data Driver")
+ __driverurl__ = "http://www.gnuenterprise.org/";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/db2/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/db2/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:42 2003
--- gnue-common/src/datasources/drivers/db2/Schema/Discovery/Introspection.py   
Thu Oct  9 21:21:12 2003
***************
*** 0 ****
--- 1,197 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[   ('table',    _('Tables'),1),
+              ('view',     _('Views'), 1),
+              ('alias',    _('Aliases'),1),
+              ('summary',  _('Summary Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = ['A','S','T','V']
+     else:
+       where_type = [string.upper(type[0])]
+ 
+ 
+     statement = \
+       "select tabschema||'.'||tabname||'.'||type full_name, " + \
+         "tabschema||'.'||tabname table_name, " + \
+         "type table_type " + \
+         "from syscat.tables where type in ('%s') and status = 'N' %s " \
+               % (string.join(where_type,"','"), where_user) + \
+           "order by tabname "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':string.lower(rs[0]), 
'name':rs[1],
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     where_user = ""
+     parts = string.split(string.upper(name),'.')
+     name = parts[-1]
+     if len(parts) > 1:
+       schema = " and tabschema='%s'" % parts[-2]
+     else:
+       schema = ""
+ 
+     statement = \
+       "select tabschema||'.'||tabname||'.'||type full_name, " + \
+         "tabschema||'.'||tabname table_name, " + \
+         "type table_type " + \
+         "from syscat.tables where tabname == '%s' and status = 'N' %s " \
+               % (name, schema) + \
+           "order by tabname "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':string.lower(rs[0]), 
'name':rs[1],
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+ 
+     try:
+       return list[0]
+     except:
+       return None
+ 
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: This does not support user-defined datatypes...
+     # TODO: it will always report such as TEXT-like fields.
+ 
+     schema, name, type = string.split(parent.id,'.')
+ 
+     cursor = self.cursor()
+ 
+     if type == 'a':
+       statement = "select base_tabschema, base_tabname " + \
+                   "from syscat.tables " + \
+                   "where tabschema = '%s' and tabname='%s'" % (schema, name)
+ 
+       GDebug.printMesg(5,statement)
+ 
+       cursor.execute(statement)
+       rs = cursor.fetchone()
+       schema, name = rs
+ 
+     statement = \
+        "select tabschema||'.'||tabname||'.'||colname, " + \
+        "colname, typename, nulls, length, scale, typeschema " + \
+        "from syscat.columns" + \
+        "where tabschema = '%s' and tabname = '%s' " % (schema, name) + \
+        "order by colno"
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': rs[1],
+              'type':'field', 'nativetype': rs[2],
+              'required': rs[3] == 'Y'}
+ 
+       if rs[2] in ('SMALLINT','INTEGER','INT','FLOAT','DOUBLE',
+                    'DECIMAL','BIGINT','REAL','DEC','NUMERIC','NUMBER',
+                    'NUM'):
+         attrs['precision'] = rs[5]
+         attrs['datatype'] = 'number'
+       elif rs[2] in ('DATE','TIME','TIMESTAMP'):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+ 
+       if rs[5] != 0:
+         attrs['length'] = rs[4]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
Index: gnue-common/src/datasources/drivers/db2/db2/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/db2/db2/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:43 2003
--- gnue-common/src/datasources/drivers/db2/db2/Connection.py   Thu Oct  9 
21:21:13 2003
***************
*** 0 ****
--- 1,67 ----
+ #
+ # 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:
+ # db2/Connection.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data stored in a DB2 database
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Connection']
+ 
+ import string
+ import sys
+ 
+ from string import lower
+ # from gnue.forms import GFOptions
+ from gnue.forms.GFError import DBError
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GDataObjects
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ try:
+   import DB2
+ except ImportError, message:
+   tmsg = _("Driver not installed: db2 for DB2 [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ from gnue.common.datasources.drivers.sqlite.Schema.Discovery.Introspection 
import Introspection
+ 
+ class Connection(DBSIG2.DataObject):
+   _DatabaseError = "Database Error"
+   _defaultBehavior = Introspection
+   _supportedDataObjects = {
+     'object': DBSIG2.DataObject_Object,
+     'sql':    DBSIG2.DataObject_SQL
+   }
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"DB2 database driver initializing")
+     try:
+       self.native = DB2.connect(uid=connectData['_username'],
+                    pwd=connectData['_password'],
+                    dsn=connectData['service'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
Index: gnue-common/src/datasources/drivers/db2/db2/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/db2/db2/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:44 2003
--- gnue-common/src/datasources/drivers/db2/db2/__init__.py     Thu Oct  9 
21:21:13 2003
***************
*** 0 ****
--- 1,33 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("IBM DB2 Data Driver")
+ __driverurl__ = "ftp://people.linuxkorea.co.kr/pub/DB2/";
+ __examples__ = ""
+ 
+ __doc__ = """
+    Supported attributes (via connections.conf or <database> tag)
+ 
+      service=    This is the DB2 DSN for your connection  (required)
+ """
+ 
Index: gnue-common/src/datasources/drivers/dbf/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/dbf/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:44 2003
--- gnue-common/src/datasources/drivers/dbf/Schema/Discovery/Introspection.py   
Thu Oct  9 21:21:14 2003
***************
*** 0 ****
--- 1,113 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('view',_('Views'),1),
+            ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     tablename=self.native.fname
+     if tablename[-4:]=='.dbf':
+         tablename=tablename[:-4]
+ 
+     list = [Schema(attrs={'id':tablename,\
+                           'name':tablename, \
+                           'type':1},\
+                    getChildSchema=self.__getFieldSchema)]
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     tablename=self.native.fname
+     if tablename[-4:]=='.dbf':
+         tablename=tablename[:-4]
+ 
+     if name==tablename:
+       return self.getSchemaList()
+     else:
+       return None
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     list = []
+     for field in self.native.fields:
+ 
+       fname=string.lower(field[0])
+ 
+       attrs={'id': "%s.%s" % (parent.id,fname), 'name': fname,
+              'type':'field', 'nativetype': field[1],
+              'required': 0}
+       if field[1] == 'C':
+         attrs['datatype']='text'
+         attrs['length']='%s' % field[2]
+       elif field[1] == 'N':
+         attrs['datatype']='number'
+       elif field[1] == 'D':
+         attrs['datatype']='date'
+       elif field[1] == 'L':
+         attrs['datatype']='boolean'
+       else:
+         GDebug.printMesg(1,'WARNING: dbf native type error: %s' % field[1])
+ 
+       list.append(Schema(attrs=attrs))
+ 
+     return list
+ 
Index: gnue-common/src/datasources/drivers/dbf/dbf/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/dbf/dbf/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:44 2003
--- gnue-common/src/datasources/drivers/dbf/dbf/Connection.py   Thu Oct  9 
21:21:15 2003
***************
*** 0 ****
--- 1,60 ----
+ #
+ # 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 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # dbf/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Virtual database driver for loading data from a DBF file
+ #
+ # NOTES:
+ # Used whenever a data has to be imported from dbase III+
+ #
+ 
+ __all__ = ['Connection']
+ 
+ from gnue.common.datasources.GDataObjects import Error
+ from gnue.common.datasource import GConnection
+ 
+ 
+ class Connection(GConnection.Connection):
+   _supportedDataObjects = {'object': DataObject,
+                            'static': DataObject} # TODO: Why static?!?
+   _DatabaseError = Error
+ 
+ 
+   # We don't do connections (we are connectionless)
+   def connect(self, connectData={}):
+     try:
+       GDebug.printMesg(3,'Open file: %s' % 
(connectData['directory']+connectData['dbname']))
+       self._dataConnection = dbf.dbf(connectData['directory']+\
+                                      connectData['dbname'])
+     except IOError:
+       tmsg = _('DBF file not found.')
+       raise self._DatabaseError, tmsg
+     except TypeError:
+       tmsg = _('Wrong file format.')
+       raise self._DatabaseError, tmsg
+ 
+     # build field list
+     self._fieldReferences=[]
+     for f in self._dataConnection.fields:
+       self._fieldReferences.append(string.lower(f[0]))
+ 
Index: gnue-common/src/datasources/drivers/dbf/dbf/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/dbf/dbf/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:44 2003
--- gnue-common/src/datasources/drivers/dbf/dbf/DataObject.py   Thu Oct  9 
21:21:15 2003
***************
*** 0 ****
--- 1,131 ----
+ #
+ # 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 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # dbf/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Virtual database driver for loading data from a DBF file
+ #
+ # NOTES:
+ # Used whenever a data has to be imported from dbase III+
+ #
+ 
+ __all__ = ['DataObject']
+ 
+ from gnue.common.apps import GDebug
+ import string
+ from gnue.common.datasources.GDataObjects import *
+ from gnue.common.drivers.special.static.Driver import *
+ import dbf
+ 
+ 
+ ###########################################################
+ #
+ # This is an static data driver for connectionless clients
+ #
+ ###########################################################
+ class DataObject (StaticDataObject): 
+ 
+   def __init__(self):
+     DataObject.__init__(self)
+     self.triggerExtensions = TriggerExtensions(self)
+     self._DatabaseError = Error
+   
+   def _createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
sql=""):
+     return DBF_ResultSet(self, masterRecordSet=masterRecordSet)
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('table',_('Tables'),1)]
+ 
+ 
+ 
+ 
+ ###########################################################
+ #
+ #
+ #
+ ###########################################################
+ class DBF_ResultSet(STATIC_ResultSet):
+ 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+ 
+     self._recordSetClass = STATIC_RecordSet
+ 
+   # Returns 1=DataObject has uncommitted changes
+   def isPending(self):
+     return 0    # Static DataObjects cannot have pending changes :)
+ 
+   # Post changes to the database
+   def post(self):
+     # Leave this here in case (for some bizarro reason)
+     # a bound dataobject uses us as a master
+     for record in (self._cachedRecords):
+       record.post()
+ 
+   # Load cacheCount number of new records
+   def _loadNextRecord(self):
+     if hasattr(self,"_alldataloaded"):
+       return 0
+     
+     # Load static data
+     for row in self._dataObject._dataConnection:
+       dict = {}
+       c=0
+       for f in self._dataObject._dataConnection.fields:
+         dict[string.lower(f[0])] = row[c]
+         c+=1
+ 
+       record=self._recordSetClass(parent=self,initialData=dict)
+       
+       self._cachedRecords.append (record)
+       
+       self._recordCount=self._recordCount+1
+ 
+     self._alldataloaded = 1
+       
+     return 1
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'static': DBF_DataObject,
+   'object': DBF_DataObject
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/dbf/dbf/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/dbf/dbf/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:44 2003
--- gnue-common/src/datasources/drivers/dbf/dbf/RecordSet.py    Thu Oct  9 
21:21:15 2003
***************
*** 0 ****
--- 1,202 ----
+ #
+ # 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 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # dbf/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Virtual database driver for loading data from a DBF file
+ #
+ # NOTES:
+ # Used whenever a data has to be imported from dbase III+
+ #
+ 
+ __all__ = ['RecordSet']
+ 
+ from gnue.common.apps import GDebug
+ import string
+ from gnue.common.datasources.GDataObjects import *
+ from gnue.common.drivers.special.static.Driver import *
+ import dbf
+ 
+ 
+ ###########################################################
+ #
+ # This is an static data driver for connectionless clients
+ # 
+ ###########################################################
+ class DBF_DataObject (STATIC_DataObject): 
+ 
+   def __init__(self):
+     DataObject.__init__(self)
+     self.triggerExtensions = TriggerExtensions(self)
+     self._DatabaseError = Error
+   
+   def _createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
sql=""):
+     return DBF_ResultSet(self, masterRecordSet=masterRecordSet)
+ 
+ 
+   # We don't do connections (we are connectionless)
+   def connect(self, connectData={}):
+     try:
+       GDebug.printMesg(3,'Open file: %s' % 
(connectData['directory']+connectData['dbname']))
+       self._dataConnection = dbf.dbf(connectData['directory']+\
+                                      connectData['dbname'])
+     except IOError:
+       tmsg = _('DBF file not found.')
+       raise self._DatabaseError, tmsg
+     except TypeError:
+       tmsg = _('Wrong file format.')
+       raise self._DatabaseError, tmsg
+ 
+     # build field list
+     self._fieldReferences=[]
+     for f in self._dataConnection.fields:
+       self._fieldReferences.append(string.lower(f[0]))
+    
+     self._postConnect()
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     tablename=self._dataConnection.fname
+     if tablename[-4:]=='.dbf':
+         tablename=tablename[:-4]
+ 
+     list = [Schema(attrs={'id':tablename,\
+                           'name':tablename, \
+                           'type':1},\
+                    getChildSchema=self.__getFieldSchema)]
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     tablename=self._dataConnection.fname
+     if tablename[-4:]=='.dbf':
+         tablename=tablename[:-4]
+ 
+     if name==tablename:
+       return self.getSchemaList()
+     else:
+       return None
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     list = []
+     for field in self._dataConnection.fields:
+       
+       fname=string.lower(field[0])
+       
+       attrs={'id': "%s.%s" % (parent.id,fname), 'name': fname,
+              'type':'field', 'nativetype': field[1],
+              'required': 0}
+       if field[1] == 'C':
+         attrs['datatype']='text'
+         attrs['length']='%s' % field[2]
+       elif field[1] == 'N':
+         attrs['datatype']='number'
+       elif field[1] == 'D':
+         attrs['datatype']='date'
+       elif field[1] == 'L':
+         attrs['datatype']='boolean'
+       else:
+         GDebug.printMesg(1,'WARNING: dbf native type error: %s' % field[1])
+ 
+       list.append(Schema(attrs=attrs))
+ 
+     return list
+ 
+ 
+ 
+ 
+ ###########################################################
+ #
+ #
+ #
+ ###########################################################
+ class DBF_ResultSet(STATIC_ResultSet):
+ 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     
+     self._recordSetClass = STATIC_RecordSet
+ 
+   # Returns 1=DataObject has uncommitted changes
+   def isPending(self):
+     return 0    # Static DataObjects cannot have pending changes :)
+ 
+   # Post changes to the database
+   def post(self):
+     # Leave this here in case (for some bizarro reason)
+     # a bound dataobject uses us as a master
+     for record in (self._cachedRecords):
+       record.post()
+ 
+   # Load cacheCount number of new records
+   def _loadNextRecord(self):
+     if hasattr(self,"_alldataloaded"):
+       return 0
+     
+     # Load static data
+     for row in self._dataObject._dataConnection:
+       dict = {}
+       c=0
+       for f in self._dataObject._dataConnection.fields:
+         dict[string.lower(f[0])] = row[c]
+         c+=1
+ 
+       record=self._recordSetClass(parent=self,initialData=dict)
+       
+       self._cachedRecords.append (record)
+       
+       self._recordCount=self._recordCount+1
+ 
+     self._alldataloaded = 1
+       
+     return 1
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'static': DBF_DataObject,
+   'object': DBF_DataObject
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/dbf/dbf/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/dbf/dbf/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:45 2003
--- gnue-common/src/datasources/drivers/dbf/dbf/ResultSet.py    Thu Oct  9 
21:21:15 2003
***************
*** 0 ****
--- 1,202 ----
+ #
+ # 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 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # dbf/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Virtual database driver for loading data from a DBF file
+ #
+ # NOTES:
+ # Used whenever a data has to be imported from dbase III+
+ #
+ 
+ __all__ = ['ResultSet']
+ 
+ from gnue.common.apps import GDebug
+ import string
+ from gnue.common.datasources.GDataObjects import *
+ from gnue.common.drivers.special.static.Driver import *
+ import dbf
+ 
+ 
+ ###########################################################
+ #
+ # This is an static data driver for connectionless clients
+ # 
+ ###########################################################
+ class DBF_DataObject (STATIC_DataObject): 
+ 
+   def __init__(self):
+     DataObject.__init__(self)
+     self.triggerExtensions = TriggerExtensions(self)
+     self._DatabaseError = Error
+   
+   def _createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
sql=""):
+     return DBF_ResultSet(self, masterRecordSet=masterRecordSet)
+ 
+ 
+   # We don't do connections (we are connectionless)
+   def connect(self, connectData={}):
+     try:
+       GDebug.printMesg(3,'Open file: %s' % 
(connectData['directory']+connectData['dbname']))
+       self._dataConnection = dbf.dbf(connectData['directory']+\
+                                      connectData['dbname'])
+     except IOError:
+       tmsg = _('DBF file not found.')
+       raise self._DatabaseError, tmsg
+     except TypeError:
+       tmsg = _('Wrong file format.')
+       raise self._DatabaseError, tmsg
+ 
+     # build field list
+     self._fieldReferences=[]
+     for f in self._dataConnection.fields:
+       self._fieldReferences.append(string.lower(f[0]))
+    
+     self._postConnect()
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     tablename=self._dataConnection.fname
+     if tablename[-4:]=='.dbf':
+         tablename=tablename[:-4]
+ 
+     list = [Schema(attrs={'id':tablename,\
+                           'name':tablename, \
+                           'type':1},\
+                    getChildSchema=self.__getFieldSchema)]
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     tablename=self._dataConnection.fname
+     if tablename[-4:]=='.dbf':
+         tablename=tablename[:-4]
+ 
+     if name==tablename:
+       return self.getSchemaList()
+     else:
+       return None
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     list = []
+     for field in self._dataConnection.fields:
+       
+       fname=string.lower(field[0])
+       
+       attrs={'id': "%s.%s" % (parent.id,fname), 'name': fname,
+              'type':'field', 'nativetype': field[1],
+              'required': 0}
+       if field[1] == 'C':
+         attrs['datatype']='text'
+         attrs['length']='%s' % field[2]
+       elif field[1] == 'N':
+         attrs['datatype']='number'
+       elif field[1] == 'D':
+         attrs['datatype']='date'
+       elif field[1] == 'L':
+         attrs['datatype']='boolean'
+       else:
+         GDebug.printMesg(1,'WARNING: dbf native type error: %s' % field[1])
+ 
+       list.append(Schema(attrs=attrs))
+ 
+     return list
+ 
+ 
+ 
+ 
+ ###########################################################
+ #
+ #
+ #
+ ###########################################################
+ class DBF_ResultSet(STATIC_ResultSet):
+ 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     
+     self._recordSetClass = STATIC_RecordSet
+ 
+   # Returns 1=DataObject has uncommitted changes
+   def isPending(self):
+     return 0    # Static DataObjects cannot have pending changes :)
+ 
+   # Post changes to the database
+   def post(self):
+     # Leave this here in case (for some bizarro reason)
+     # a bound dataobject uses us as a master
+     for record in (self._cachedRecords):
+       record.post()
+ 
+   # Load cacheCount number of new records
+   def _loadNextRecord(self):
+     if hasattr(self,"_alldataloaded"):
+       return 0
+     
+     # Load static data
+     for row in self._dataObject._dataConnection:
+       dict = {}
+       c=0
+       for f in self._dataObject._dataConnection.fields:
+         dict[string.lower(f[0])] = row[c]
+         c+=1
+ 
+       record=self._recordSetClass(parent=self,initialData=dict)
+       
+       self._cachedRecords.append (record)
+       
+       self._recordCount=self._recordCount+1
+ 
+     self._alldataloaded = 1
+       
+     return 1
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'static': DBF_DataObject,
+   'object': DBF_DataObject
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/dbf/dbf/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/dbf/dbf/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:45 2003
--- gnue-common/src/datasources/drivers/dbf/dbf/__init__.py     Thu Oct  9 
21:21:15 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("DBF File Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: 
gnue-common/src/datasources/drivers/gadfly/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/gadfly/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:45 2003
--- 
gnue-common/src/datasources/drivers/gadfly/Schema/Discovery/Introspection.py    
    Thu Oct  9 21:21:15 2003
***************
*** 0 ****
--- 1,152 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('view',_('Views'),1),
+            ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+   #
+   # Schema (metadata) functions
+   #
+   def getSchemaList(self, type=None):
+ 
+     statement = "select * from __table_names__"
+ 
+     cursor = self.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       # exclude any system tables and views. f.e. __table_names__
+       if rs[1][:2]!="__":
+         list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                 'type':rs[0] == 1 and 'view' or 'table',},
+                                        getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "SELECT * from __table_names__ WHERE TABLE_NAME='%s'" % (name)
+ 
+     cursor = self.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                 'type':rs[0] == 1 and 'view' or 'table',},
+                                        getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: Read whole definitions from __DATADEFS__ and parse them
+     #       to distinguish between varchar, float and integer
+     
+     statement = "SELECT * FROM __COLUMNS__ WHERE TABLE_NAME='%s'" % parent.id
+ 
+     cursor = self.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+     columns = cursor.description
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       #nativetype = string.split(string.replace(rs[1],')',''),'(')
+ 
+ 
+       attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
+              'type':'field', 'nativetype': 'varchar',
+              'required': 0}
+ 
+       #if nativetype[0] in ('int','integer','bigint','mediumint',
+       #                     'smallint','tinyint','float','real',
+       #                     'double','decimal'):
+       #  attrs['datatype']='number'
+       #elif nativetype[0] in ('date','time','timestamp','datetime'):
+       #  attrs['datatype']='date'
+       #else:
+       #  attrs['datatype']='text'
+ 
+       ## MORE EVILNESS
+       attrs['datatype']='text'
+       ##END HACK
+       
+       #try:
+       #  if len(nativetype) == 2:
+       #    attrs['length'] = int(string.split(nativetype[1])[0])
+       #except ValueError:
+       #  GDebug.printMesg(1,'WARNING: mysql native type error: %s' % 
nativetype)
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
Index: gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:45 2003
--- gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py     Thu Oct 
 9 21:21:15 2003
***************
*** 0 ****
--- 1,115 ----
+ #
+ # 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:
+ # gadfly/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Gadfly
+ #
+ # NOTES:
+ # The Gadfly notes state that it is not safe to use in a multi-user 
environment
+ # where there may be concurrent read/writes. Use at own risk :)
+ 
+ __all__ = ['Connection']
+ 
+ import string
+ import sys
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GDataObjects
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ try:
+   import gadfly
+ except ImportError, message:
+   tmsg = _("Driver not installed: gadfly driver\n\n[%s") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ 
+ ##### EVIL HACK
+ class Error(StandardError):
+   """Generic Error"""
+ 
+ class InterfaceError(Error):
+   """Interface Error"""
+ 
+ class DatabaseError(InterfaceError):
+   """DB Error"""
+ 
+ class DataError(DatabaseError):
+   """Data Error"""
+ 
+ class OperationalError(DatabaseError):
+   """Operational Error"""
+ 
+ class IntegrityError(DatabaseError):
+   """Integrity Error"""
+ 
+ ##### END EVIL HACK
+ 
+ class Connection(DBSIG2.Connection):
+ 
+   _DatabaseError = Error
+   _supportedDataObjects = {
+    'object': DataObject_Object,
+    'sql':    DataObject_SQL
+   }
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Gadfly database driver initializing")
+     #GDebug.printMesg(1,"Connecting with %s, %s" %( connectData['_dbname'], 
connectData['directory']))
+     try:
+       self.native = gadfly.gadfly(connectData['dbname'],
+                                            connectData['directory'])
+     except self._DatabaseError, value:
+       #GDebug.printMesg(1,"Boom")
+       raise GDataObjects.LoginError, value
+ 
+     self._beginTransaction()
+ 
+ 
+   def _beginTransaction(self):
+     try:
+       self.native.begin()
+     except:
+       pass
+ 
+   # This should be over-ridden only if driver needs more than user/pass
+   def getLoginFields(self):
+     return []
+ 
+ 
+   #
+   # Extensions
+   #
+ 
+   # Return the current date, according to database
+ #  def getDate(self):
+ #    pass
+ 
+   # Return a sequence number from sequence 'name'
+ #  def getSequence(self, name):
+ #    pass
+ 
+   # Run the SQL statement 'statement'
+ #  def sql(self, statement):
+ #    pass
+ 
Index: gnue-common/src/datasources/drivers/gadfly/gadfly/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/gadfly/gadfly/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:45 2003
--- gnue-common/src/datasources/drivers/gadfly/gadfly/DataObject.py     Thu Oct 
 9 21:21:15 2003
***************
*** 0 ****
--- 1,338 ----
+ #
+ # 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:
+ # gadfly/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Gadfly
+ #
+ # NOTES:
+ # The Gadfly notes state that it is not safe to use in a multi-user 
environment
+ # where there may be concurrent read/writes. Use at own risk :)
+ 
+ 
+ import string
+ import sys
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GDataObjects
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try: 
+   import gadfly
+ except ImportError, mesg:
+   GDebug.printMesg(1,mesg)
+   print "-"*79
+   print _("\nCould not load gadfly.  For Gadfly support, please install \n") \
+       + _("GadflyB5 1.0.0 pr1 or later from") \
+       + "http://gadfly.sourceforge.net\n";
+   print _("Error:  %s") % mesg
+   print "-"*79
+   sys.exit()
+ 
+ 
+ 
+ class Gadfly_RecordSet(DBSIG2.RecordSet): 
+   pass
+ 
+ 
+ class Gadfly_ResultSet(DBSIG2.ResultSet): 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     cursor.rowcount=0
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Gadfly_RecordSet
+     
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         rsets = self._cursor.fetchall()
+       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:
+         return 0
+     else:
+      return 0
+ 
+ ##### EVIL HACK
+ class Error(StandardError):
+   """Generic Error"""
+ 
+ class InterfaceError(Error):
+   """Interface Error"""
+   
+ class DatabaseError(InterfaceError):
+   """DB Error"""
+ 
+ class DataError(DatabaseError):
+   """Data Error"""
+ 
+ class OperationalError(DatabaseError):
+   """Operational Error"""
+   
+ class IntegrityError(DatabaseError):
+   """Integrity Error"""
+ 
+ ##### END EVIL HACK
+ 
+ class Gadfly_DataObject(DBSIG2.DataObject):
+ 
+ 
+   def __init__(self): 
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = Error
+     self._resultSetClass = Gadfly_ResultSet
+ 
+     # LIKE is not supported on database level at the moment
+     # there should be used other ways to emulate it
+     # until that works, do a = instead of a like
+     # EVIL HACK
+     self.conditionElements.update({\
+        'like':            (2,   2, '%s = %s',             None     ),\
+        'notlike':         (2,   2, 'NOT (%s = %s)',       None     )})
+     # END EVIL HACK
+ 
+ 
+ 
+   def connect(self, connectData={}): 
+     GDebug.printMesg(1,"Gadfly database driver initializing")
+     #GDebug.printMesg(1,"Connecting with %s, %s" %( connectData['_dbname'], 
connectData['directory']))
+     try:
+       self._dataConnection = gadfly.gadfly(connectData['dbname'],
+                                            connectData['directory'])
+     except self._DatabaseError, value:
+       #GDebug.printMesg(1,"Boom")
+       raise GDataObjects.LoginError, value
+       
+     self._beginTransaction()
+     self._postConnect()
+ 
+ 
+   def _postConnect(self): 
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   def _beginTransaction(self):
+     try:
+       self._dataConnection.begin()
+     except: 
+       pass
+ 
+   # This should be over-ridden only if driver needs more than user/pass
+   def getLoginFields(self):
+     return []
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     statement = "select * from __table_names__"
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)    
+ 
+     list = []
+     for rs in cursor.fetchall():
+       # exclude any system tables and views. f.e. __table_names__
+       if rs[1][:2]!="__":       
+         list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                 'type':rs[0] == 1 and 'view' or 'table',},
+                                        getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "SELECT * from __table_names__ WHERE TABLE_NAME='%s'" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                 'type':rs[0] == 1 and 'view' or 'table',},
+                                        getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: Read whole definitions from __DATADEFS__ and parse them
+     #       to distinguish between varchar, float and integer
+     
+     statement = "SELECT * FROM __COLUMNS__ WHERE TABLE_NAME='%s'" % parent.id
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+     columns = cursor.description
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       #nativetype = string.split(string.replace(rs[1],')',''),'(')
+ 
+ 
+       attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
+              'type':'field', 'nativetype': 'varchar',
+              'required': 0}
+ 
+       #if nativetype[0] in ('int','integer','bigint','mediumint',
+       #                     'smallint','tinyint','float','real',
+       #                     'double','decimal'):
+       #  attrs['datatype']='number'
+       #elif nativetype[0] in ('date','time','timestamp','datetime'):
+       #  attrs['datatype']='date'
+       #else:
+       #  attrs['datatype']='text'
+ 
+       ## MORE EVILNESS
+       attrs['datatype']='text'
+       ##END HACK
+       
+       #try:
+       #  if len(nativetype) == 2:
+       #    attrs['length'] = int(string.split(nativetype[1])[0])
+       #except ValueError:
+       #  GDebug.printMesg(1,'WARNING: mysql native type error: %s' % 
nativetype)
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+ 
+ 
+ 
+ class Gadfly_DataObject_Object(Gadfly_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Gadfly_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+   def _getQueryCount(self,conditions={}):
+     cursor = self._dataConnection.cursor()
+ 
+     cursor.execute(self._buildQueryCount(conditions))
+     # GADFLY throws an error if executing COUNT(*) on an empty set
+     try:
+       rs = cursor.fetchone()
+       return int(rs[0])
+     except:
+       return 0
+ 
+   def _buildQueryCount(self, conditions={}):
+     # GADFLY seems to hate big letter "SELECT"
+     q = "select count(*) from %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+ class Gadfly_DataObject_SQL(Gadfly_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Gadfly_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Gadfly_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #  
+ class TriggerExtensions: 
+ 
+   def __init__(self, connection): 
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+ #  def getDate(self): 
+ #    pass
+ 
+   # Return a sequence number from sequence 'name' 
+ #  def getSequence(self, name): 
+ #    pass
+ 
+   # Run the SQL statement 'statement'
+ #  def sql(self, statement): 
+ #    pass
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe 
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ # 
+ supportedDataObjects = {
+   'object': Gadfly_DataObject_Object,
+   'sql':    Gadfly_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/gadfly/gadfly/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/gadfly/gadfly/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:46 2003
--- gnue-common/src/datasources/drivers/gadfly/gadfly/RecordSet.py      Thu Oct 
 9 21:21:15 2003
***************
*** 0 ****
--- 1,338 ----
+ #
+ # 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:
+ # gadfly/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Gadfly
+ #
+ # NOTES:
+ # The Gadfly notes state that it is not safe to use in a multi-user 
environment
+ # where there may be concurrent read/writes. Use at own risk :)
+ 
+ 
+ import string
+ import sys
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GDataObjects
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try: 
+   import gadfly
+ except ImportError, mesg:
+   GDebug.printMesg(1,mesg)
+   print "-"*79
+   print _("\nCould not load gadfly.  For Gadfly support, please install \n") \
+       + _("GadflyB5 1.0.0 pr1 or later from") \
+       + "http://gadfly.sourceforge.net\n";
+   print _("Error:  %s") % mesg
+   print "-"*79
+   sys.exit()
+ 
+ 
+ 
+ class Gadfly_RecordSet(DBSIG2.RecordSet): 
+   pass
+ 
+ 
+ class Gadfly_ResultSet(DBSIG2.ResultSet): 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     cursor.rowcount=0
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Gadfly_RecordSet
+     
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         rsets = self._cursor.fetchall()
+       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:
+         return 0
+     else:
+      return 0
+ 
+ ##### EVIL HACK
+ class Error(StandardError):
+   """Generic Error"""
+ 
+ class InterfaceError(Error):
+   """Interface Error"""
+   
+ class DatabaseError(InterfaceError):
+   """DB Error"""
+ 
+ class DataError(DatabaseError):
+   """Data Error"""
+ 
+ class OperationalError(DatabaseError):
+   """Operational Error"""
+   
+ class IntegrityError(DatabaseError):
+   """Integrity Error"""
+ 
+ ##### END EVIL HACK
+ 
+ class Gadfly_DataObject(DBSIG2.DataObject):
+ 
+ 
+   def __init__(self): 
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = Error
+     self._resultSetClass = Gadfly_ResultSet
+ 
+     # LIKE is not supported on database level at the moment
+     # there should be used other ways to emulate it
+     # until that works, do a = instead of a like
+     # EVIL HACK
+     self.conditionElements.update({\
+        'like':            (2,   2, '%s = %s',             None     ),\
+        'notlike':         (2,   2, 'NOT (%s = %s)',       None     )})
+     # END EVIL HACK
+ 
+ 
+ 
+   def connect(self, connectData={}): 
+     GDebug.printMesg(1,"Gadfly database driver initializing")
+     #GDebug.printMesg(1,"Connecting with %s, %s" %( connectData['_dbname'], 
connectData['directory']))
+     try:
+       self._dataConnection = gadfly.gadfly(connectData['dbname'],
+                                            connectData['directory'])
+     except self._DatabaseError, value:
+       #GDebug.printMesg(1,"Boom")
+       raise GDataObjects.LoginError, value
+       
+     self._beginTransaction()
+     self._postConnect()
+ 
+ 
+   def _postConnect(self): 
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   def _beginTransaction(self):
+     try:
+       self._dataConnection.begin()
+     except: 
+       pass
+ 
+   # This should be over-ridden only if driver needs more than user/pass
+   def getLoginFields(self):
+     return []
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     statement = "select * from __table_names__"
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)    
+ 
+     list = []
+     for rs in cursor.fetchall():
+       # exclude any system tables and views. f.e. __table_names__
+       if rs[1][:2]!="__":       
+         list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                 'type':rs[0] == 1 and 'view' or 'table',},
+                                        getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "SELECT * from __table_names__ WHERE TABLE_NAME='%s'" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                 'type':rs[0] == 1 and 'view' or 'table',},
+                                        getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: Read whole definitions from __DATADEFS__ and parse them
+     #       to distinguish between varchar, float and integer
+     
+     statement = "SELECT * FROM __COLUMNS__ WHERE TABLE_NAME='%s'" % parent.id
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+     columns = cursor.description
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       #nativetype = string.split(string.replace(rs[1],')',''),'(')
+ 
+ 
+       attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
+              'type':'field', 'nativetype': 'varchar',
+              'required': 0}
+ 
+       #if nativetype[0] in ('int','integer','bigint','mediumint',
+       #                     'smallint','tinyint','float','real',
+       #                     'double','decimal'):
+       #  attrs['datatype']='number'
+       #elif nativetype[0] in ('date','time','timestamp','datetime'):
+       #  attrs['datatype']='date'
+       #else:
+       #  attrs['datatype']='text'
+ 
+       ## MORE EVILNESS
+       attrs['datatype']='text'
+       ##END HACK
+       
+       #try:
+       #  if len(nativetype) == 2:
+       #    attrs['length'] = int(string.split(nativetype[1])[0])
+       #except ValueError:
+       #  GDebug.printMesg(1,'WARNING: mysql native type error: %s' % 
nativetype)
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+ 
+ 
+ 
+ class Gadfly_DataObject_Object(Gadfly_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Gadfly_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+   def _getQueryCount(self,conditions={}):
+     cursor = self._dataConnection.cursor()
+ 
+     cursor.execute(self._buildQueryCount(conditions))
+     # GADFLY throws an error if executing COUNT(*) on an empty set
+     try:
+       rs = cursor.fetchone()
+       return int(rs[0])
+     except:
+       return 0
+ 
+   def _buildQueryCount(self, conditions={}):
+     # GADFLY seems to hate big letter "SELECT"
+     q = "select count(*) from %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+ class Gadfly_DataObject_SQL(Gadfly_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Gadfly_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Gadfly_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #  
+ class TriggerExtensions: 
+ 
+   def __init__(self, connection): 
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+ #  def getDate(self): 
+ #    pass
+ 
+   # Return a sequence number from sequence 'name' 
+ #  def getSequence(self, name): 
+ #    pass
+ 
+   # Run the SQL statement 'statement'
+ #  def sql(self, statement): 
+ #    pass
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe 
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ # 
+ supportedDataObjects = {
+   'object': Gadfly_DataObject_Object,
+   'sql':    Gadfly_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/gadfly/gadfly/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/gadfly/gadfly/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:46 2003
--- gnue-common/src/datasources/drivers/gadfly/gadfly/ResultSet.py      Thu Oct 
 9 21:21:15 2003
***************
*** 0 ****
--- 1,338 ----
+ #
+ # 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:
+ # gadfly/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Gadfly
+ #
+ # NOTES:
+ # The Gadfly notes state that it is not safe to use in a multi-user 
environment
+ # where there may be concurrent read/writes. Use at own risk :)
+ 
+ 
+ import string
+ import sys
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GDataObjects
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try: 
+   import gadfly
+ except ImportError, mesg:
+   GDebug.printMesg(1,mesg)
+   print "-"*79
+   print _("\nCould not load gadfly.  For Gadfly support, please install \n") \
+       + _("GadflyB5 1.0.0 pr1 or later from") \
+       + "http://gadfly.sourceforge.net\n";
+   print _("Error:  %s") % mesg
+   print "-"*79
+   sys.exit()
+ 
+ 
+ 
+ class Gadfly_RecordSet(DBSIG2.RecordSet): 
+   pass
+ 
+ 
+ class Gadfly_ResultSet(DBSIG2.ResultSet): 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     cursor.rowcount=0
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Gadfly_RecordSet
+     
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         rsets = self._cursor.fetchall()
+       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:
+         return 0
+     else:
+      return 0
+ 
+ ##### EVIL HACK
+ class Error(StandardError):
+   """Generic Error"""
+ 
+ class InterfaceError(Error):
+   """Interface Error"""
+   
+ class DatabaseError(InterfaceError):
+   """DB Error"""
+ 
+ class DataError(DatabaseError):
+   """Data Error"""
+ 
+ class OperationalError(DatabaseError):
+   """Operational Error"""
+   
+ class IntegrityError(DatabaseError):
+   """Integrity Error"""
+ 
+ ##### END EVIL HACK
+ 
+ class Gadfly_DataObject(DBSIG2.DataObject):
+ 
+ 
+   def __init__(self): 
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = Error
+     self._resultSetClass = Gadfly_ResultSet
+ 
+     # LIKE is not supported on database level at the moment
+     # there should be used other ways to emulate it
+     # until that works, do a = instead of a like
+     # EVIL HACK
+     self.conditionElements.update({\
+        'like':            (2,   2, '%s = %s',             None     ),\
+        'notlike':         (2,   2, 'NOT (%s = %s)',       None     )})
+     # END EVIL HACK
+ 
+ 
+ 
+   def connect(self, connectData={}): 
+     GDebug.printMesg(1,"Gadfly database driver initializing")
+     #GDebug.printMesg(1,"Connecting with %s, %s" %( connectData['_dbname'], 
connectData['directory']))
+     try:
+       self._dataConnection = gadfly.gadfly(connectData['dbname'],
+                                            connectData['directory'])
+     except self._DatabaseError, value:
+       #GDebug.printMesg(1,"Boom")
+       raise GDataObjects.LoginError, value
+       
+     self._beginTransaction()
+     self._postConnect()
+ 
+ 
+   def _postConnect(self): 
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   def _beginTransaction(self):
+     try:
+       self._dataConnection.begin()
+     except: 
+       pass
+ 
+   # This should be over-ridden only if driver needs more than user/pass
+   def getLoginFields(self):
+     return []
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     statement = "select * from __table_names__"
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)    
+ 
+     list = []
+     for rs in cursor.fetchall():
+       # exclude any system tables and views. f.e. __table_names__
+       if rs[1][:2]!="__":       
+         list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                 'type':rs[0] == 1 and 'view' or 'table',},
+                                        getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "SELECT * from __table_names__ WHERE TABLE_NAME='%s'" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                 'type':rs[0] == 1 and 'view' or 'table',},
+                                        getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: Read whole definitions from __DATADEFS__ and parse them
+     #       to distinguish between varchar, float and integer
+     
+     statement = "SELECT * FROM __COLUMNS__ WHERE TABLE_NAME='%s'" % parent.id
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+     columns = cursor.description
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       #nativetype = string.split(string.replace(rs[1],')',''),'(')
+ 
+ 
+       attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
+              'type':'field', 'nativetype': 'varchar',
+              'required': 0}
+ 
+       #if nativetype[0] in ('int','integer','bigint','mediumint',
+       #                     'smallint','tinyint','float','real',
+       #                     'double','decimal'):
+       #  attrs['datatype']='number'
+       #elif nativetype[0] in ('date','time','timestamp','datetime'):
+       #  attrs['datatype']='date'
+       #else:
+       #  attrs['datatype']='text'
+ 
+       ## MORE EVILNESS
+       attrs['datatype']='text'
+       ##END HACK
+       
+       #try:
+       #  if len(nativetype) == 2:
+       #    attrs['length'] = int(string.split(nativetype[1])[0])
+       #except ValueError:
+       #  GDebug.printMesg(1,'WARNING: mysql native type error: %s' % 
nativetype)
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+ 
+ 
+ 
+ class Gadfly_DataObject_Object(Gadfly_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Gadfly_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+   def _getQueryCount(self,conditions={}):
+     cursor = self._dataConnection.cursor()
+ 
+     cursor.execute(self._buildQueryCount(conditions))
+     # GADFLY throws an error if executing COUNT(*) on an empty set
+     try:
+       rs = cursor.fetchone()
+       return int(rs[0])
+     except:
+       return 0
+ 
+   def _buildQueryCount(self, conditions={}):
+     # GADFLY seems to hate big letter "SELECT"
+     q = "select count(*) from %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+ class Gadfly_DataObject_SQL(Gadfly_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Gadfly_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Gadfly_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #  
+ class TriggerExtensions: 
+ 
+   def __init__(self, connection): 
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+ #  def getDate(self): 
+ #    pass
+ 
+   # Return a sequence number from sequence 'name' 
+ #  def getSequence(self, name): 
+ #    pass
+ 
+   # Run the SQL statement 'statement'
+ #  def sql(self, statement): 
+ #    pass
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe 
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ # 
+ supportedDataObjects = {
+   'object': Gadfly_DataObject_Object,
+   'sql':    Gadfly_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/gadfly/gadfly/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/gadfly/gadfly/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:46 2003
--- gnue-common/src/datasources/drivers/gadfly/gadfly/__init__.py       Thu Oct 
 9 21:21:15 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("Gadfly Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: 
gnue-common/src/datasources/drivers/informix/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/informix/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:46 2003
--- 
gnue-common/src/datasources/drivers/informix/Schema/Discovery/Introspection.py  
    Thu Oct  9 21:21:16 2003
***************
*** 0 ****
--- 1,59 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('view',_('Views'),1),
+            ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
Index: gnue-common/src/datasources/drivers/informix/informix/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/informix/informix/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:47 2003
--- gnue-common/src/datasources/drivers/informix/informix/Connection.py Thu Oct 
 9 21:21:16 2003
***************
*** 0 ****
--- 1,76 ----
+ #
+ # 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:
+ # informix/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Alexander Kuznetsov's
+ # Informix/Python Driver  *  Requires Kinfxdb 0.2+
+ # (http://thor.prohosting.com/~alexan/pub/Kinfxdb/Kinfxdb-0.2.tar.gz)
+ #
+ # NOTES:
+ #
+ #     dbame=      This is the Informix database to use (required)
+ #     host=      This is the Informix host for your connection  (optional)
+ #
+ 
+ __all__ = ['Connection']
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ try:
+   import informixdb as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Kinfxdb for Informix [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ 
+ class Connection(DBSIG2.Connection):
+ 
+   _DatabaseError = SIG2api.DatabaseError
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Informix database driver initializing")
+     try:
+       if connectData.has_key('host') and len(connectData['host']):
+         db = connectData['dbname'] + "@" + connectData['host']
+       else:
+         db = connectData['dbname']
+       self.native = SIG2api.connect( \
+                    dbname=connectData['dbname'], \
+                    user=connectData['_username'], \
+                    passwd=connectData['_password'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
Index: gnue-common/src/datasources/drivers/informix/informix/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/informix/informix/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:47 2003
--- gnue-common/src/datasources/drivers/informix/informix/DataObject.py Thu Oct 
 9 21:21:16 2003
***************
*** 0 ****
--- 1,163 ----
+ #
+ # 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:
+ # informix/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Alexander Kuznetsov's
+ # Informix/Python Driver  *  Requires Kinfxdb 0.2+
+ # (http://thor.prohosting.com/~alexan/pub/Kinfxdb/Kinfxdb-0.2.tar.gz)
+ #
+ # NOTES:
+ #
+ #     dbame=      This is the Informix database to use (required)
+ #     host=      This is the Informix host for your connection  (optional)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import informixdb as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Kinfxdb for Informix [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Informix_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Informix_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Informix_RecordSet
+     self._uniqueIdField = "__GNUeF__uniqueKey_%s" % (self._dataObject.table)
+     self._uniqueIdFormat = "ROWID='%s'"
+ 
+ 
+ 
+ class Informix_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Informix_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Informix database driver initializing")
+     try:
+       if connectData.has_key('host') and len(connectData['host']):
+         db = connectData['dbname'] + "@" + connectData['host']
+       else:
+         db = connectData['dbname']
+       self._dataConnection = SIG2api.connect( \
+                    dbname=connectData['dbname'], \
+                    user=connectData['_username'], \
+                    passwd=connectData['_password'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Informix_DataObject_Object(Informix_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Informix_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class Informix_DataObject_SQL(Informix_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Informix_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Informix_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Informix_DataObject_Object,
+   'sql':    Informix_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/informix/informix/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/informix/informix/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:48 2003
--- gnue-common/src/datasources/drivers/informix/informix/RecordSet.py  Thu Oct 
 9 21:21:16 2003
***************
*** 0 ****
--- 1,163 ----
+ #
+ # 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:
+ # informix/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Alexander Kuznetsov's
+ # Informix/Python Driver  *  Requires Kinfxdb 0.2+
+ # (http://thor.prohosting.com/~alexan/pub/Kinfxdb/Kinfxdb-0.2.tar.gz)
+ #
+ # NOTES:
+ #
+ #     dbame=      This is the Informix database to use (required)
+ #     host=      This is the Informix host for your connection  (optional)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import informixdb as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Kinfxdb for Informix [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Informix_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Informix_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Informix_RecordSet
+     self._uniqueIdField = "__GNUeF__uniqueKey_%s" % (self._dataObject.table)
+     self._uniqueIdFormat = "ROWID='%s'"
+ 
+ 
+ 
+ class Informix_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Informix_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Informix database driver initializing")
+     try:
+       if connectData.has_key('host') and len(connectData['host']):
+         db = connectData['dbname'] + "@" + connectData['host']
+       else:
+         db = connectData['dbname']
+       self._dataConnection = SIG2api.connect( \
+                    dbname=connectData['dbname'], \
+                    user=connectData['_username'], \
+                    passwd=connectData['_password'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Informix_DataObject_Object(Informix_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Informix_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class Informix_DataObject_SQL(Informix_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Informix_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Informix_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Informix_DataObject_Object,
+   'sql':    Informix_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/informix/informix/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/informix/informix/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:48 2003
--- gnue-common/src/datasources/drivers/informix/informix/ResultSet.py  Thu Oct 
 9 21:21:16 2003
***************
*** 0 ****
--- 1,163 ----
+ #
+ # 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:
+ # informix/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Alexander Kuznetsov's
+ # Informix/Python Driver  *  Requires Kinfxdb 0.2+
+ # (http://thor.prohosting.com/~alexan/pub/Kinfxdb/Kinfxdb-0.2.tar.gz)
+ #
+ # NOTES:
+ #
+ #     dbame=      This is the Informix database to use (required)
+ #     host=      This is the Informix host for your connection  (optional)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import informixdb as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Kinfxdb for Informix [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Informix_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Informix_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Informix_RecordSet
+     self._uniqueIdField = "__GNUeF__uniqueKey_%s" % (self._dataObject.table)
+     self._uniqueIdFormat = "ROWID='%s'"
+ 
+ 
+ 
+ class Informix_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Informix_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Informix database driver initializing")
+     try:
+       if connectData.has_key('host') and len(connectData['host']):
+         db = connectData['dbname'] + "@" + connectData['host']
+       else:
+         db = connectData['dbname']
+       self._dataConnection = SIG2api.connect( \
+                    dbname=connectData['dbname'], \
+                    user=connectData['_username'], \
+                    passwd=connectData['_password'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Informix_DataObject_Object(Informix_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Informix_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class Informix_DataObject_SQL(Informix_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Informix_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Informix_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Informix_DataObject_Object,
+   'sql':    Informix_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/informix/informix/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/informix/informix/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:48 2003
--- gnue-common/src/datasources/drivers/informix/informix/__init__.py   Thu Oct 
 9 21:21:16 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("Informix Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: 
gnue-common/src/datasources/drivers/ingres/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/ingres/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:48 2003
--- 
gnue-common/src/datasources/drivers/ingres/Schema/Discovery/Introspection.py    
    Thu Oct  9 21:21:18 2003
***************
*** 0 ****
--- 1,59 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('view',_('Views'),1),
+            ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
Index: gnue-common/src/datasources/drivers/ingres/ingres/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/ingres/ingres/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:48 2003
--- gnue-common/src/datasources/drivers/ingres/ingres/Connection.py     Thu Oct 
 9 21:21:18 2003
***************
*** 0 ****
--- 1,72 ----
+ #
+ # 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:
+ # ingres/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Holger Meyer's Ingres/Python Driver
+ # (including OpenIngres 1.2, CA Ingres 6.4, CA Ingres II)
+ # Requires ingmod (http://www.informatik.uni-rostock.de/~hme/software/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     dbame=      This is the Ingres database to use (required)
+ #
+ 
+ __all__ = ['Connection']
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ from DataObjects import *
+ 
+ try:
+   import ingmod as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: ingmod for Ingres/Ingres II/OpenIngres 
[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ 
+ class Connection(DBSIG2.Connection):
+   _DatabaseError = SIG2api.DatabaseError
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Ingres database driver initializing")
+     try:
+       # TODO: I have no clue how to pass a Password!!!!!
+       self.native = SIG2api.connect(connectData['dbname'], \
+                 user=connectData['_username'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
Index: gnue-common/src/datasources/drivers/ingres/ingres/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/ingres/ingres/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:48 2003
--- gnue-common/src/datasources/drivers/ingres/ingres/DataObject.py     Thu Oct 
 9 21:21:18 2003
***************
*** 0 ****
--- 1,155 ----
+ #
+ # 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:
+ # ingres/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Holger Meyer's Ingres/Python Driver
+ # (including OpenIngres 1.2, CA Ingres 6.4, CA Ingres II)
+ # Requires ingmod (http://www.informatik.uni-rostock.de/~hme/software/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     dbame=      This is the Ingres database to use (required)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import ingmod as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: ingmod for Ingres/Ingres II/OpenIngres 
[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Ingres_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Ingres_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Ingres_RecordSet
+ 
+ 
+ class Ingres_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Ingres_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Ingres database driver initializing")
+     try:
+       # TODO: I have no clue how to pass a Password!!!!!
+       self._dataConnection = SIG2api.connect(connectData['dbname'], \
+                 user=connectData['_username'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Ingres_DataObject_Object(Ingres_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Ingres_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail, 
additionalSQL)
+ 
+ 
+ class Ingres_DataObject_SQL(Ingres_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Ingres_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Ingres_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Ingres_DataObject_Object,
+   'sql':    Ingres_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/ingres/ingres/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/ingres/ingres/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:49 2003
--- gnue-common/src/datasources/drivers/ingres/ingres/RecordSet.py      Thu Oct 
 9 21:21:18 2003
***************
*** 0 ****
--- 1,155 ----
+ #
+ # 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:
+ # ingres/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Holger Meyer's Ingres/Python Driver
+ # (including OpenIngres 1.2, CA Ingres 6.4, CA Ingres II)
+ # Requires ingmod (http://www.informatik.uni-rostock.de/~hme/software/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     dbame=      This is the Ingres database to use (required)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import ingmod as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: ingmod for Ingres/Ingres II/OpenIngres 
[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Ingres_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Ingres_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Ingres_RecordSet
+ 
+ 
+ class Ingres_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Ingres_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Ingres database driver initializing")
+     try:
+       # TODO: I have no clue how to pass a Password!!!!!
+       self._dataConnection = SIG2api.connect(connectData['dbname'], \
+                 user=connectData['_username'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Ingres_DataObject_Object(Ingres_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Ingres_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail, 
additionalSQL)
+ 
+ 
+ class Ingres_DataObject_SQL(Ingres_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Ingres_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Ingres_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Ingres_DataObject_Object,
+   'sql':    Ingres_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/ingres/ingres/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/ingres/ingres/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:49 2003
--- gnue-common/src/datasources/drivers/ingres/ingres/ResultSet.py      Thu Oct 
 9 21:21:18 2003
***************
*** 0 ****
--- 1,155 ----
+ #
+ # 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:
+ # ingres/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Holger Meyer's Ingres/Python Driver
+ # (including OpenIngres 1.2, CA Ingres 6.4, CA Ingres II)
+ # Requires ingmod (http://www.informatik.uni-rostock.de/~hme/software/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     dbame=      This is the Ingres database to use (required)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import ingmod as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: ingmod for Ingres/Ingres II/OpenIngres 
[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Ingres_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Ingres_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Ingres_RecordSet
+ 
+ 
+ class Ingres_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Ingres_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Ingres database driver initializing")
+     try:
+       # TODO: I have no clue how to pass a Password!!!!!
+       self._dataConnection = SIG2api.connect(connectData['dbname'], \
+                 user=connectData['_username'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Ingres_DataObject_Object(Ingres_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Ingres_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail, 
additionalSQL)
+ 
+ 
+ class Ingres_DataObject_SQL(Ingres_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Ingres_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Ingres_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Ingres_DataObject_Object,
+   'sql':    Ingres_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/ingres/ingres/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/ingres/ingres/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:49 2003
--- gnue-common/src/datasources/drivers/ingres/ingres/__init__.py       Thu Oct 
 9 21:21:18 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("Ingres Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: 
gnue-common/src/datasources/drivers/interbase/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/interbase/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:50 2003
--- 
gnue-common/src/datasources/drivers/interbase/Schema/Discovery/Introspection.py 
    Thu Oct  9 21:21:19 2003
***************
*** 0 ****
--- 1,40 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+   pass
\ No newline at end of file
Index: gnue-common/src/datasources/drivers/interbase/interbase/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/interbase/interbase/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:50 2003
--- gnue-common/src/datasources/drivers/interbase/interbase/Connection.py       
Thu Oct  9 21:21:19 2003
***************
*** 0 ****
--- 1,337 ----
+ #
+ # 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:
+ # interbase/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via the Kinterbasdb Interbase/Firebird 
Python Driver
+ # Requires Kinterbasdb > 3.0 (http://kinterbasdb.sourceforge.net/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the Interbase host for your connection  (required)
+ #     dbame=      This is the Interbase database to use (required)
+ #
+ 
+ __all__ = ['Connection']
+ 
+ from string import upper, lower, rstrip
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ try:
+   import kinterbasdb as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Kinterbasdb for Interbase [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = RecordSet
+ 
+ 
+ class DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = ResultSet
+     self._primaryKeyFields = []
+ 
+     # The date/time format used in insert/select statements
+     # (based on format used for time.strftime())
+     self._dateTimeFormat = "cast('%Y-%m-%d %H:%M:%S' as timestamp)"
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Interbase database driver initializing")
+ 
+     try:
+       charset = connectData['charset']
+     except KeyError:
+       charset = ""
+ 
+     try:
+       self.native = SIG2api.connect( \
+                  user=str(connectData['_username']), \
+                  password=str(connectData['_password']), \
+                  charset=charset, \
+                  database=connectData['dbname'], \
+                  host=connectData['host'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+   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.native.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)
+ 
+         #kinterbasdb 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
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+   # This excludes any system tables and views.
+     statement = "select rdb$relation_name, rdb$view_source "+\
+                       "from rdb$relations " + \
+                       "where rdb$system_flag=0 " + \
+                       "order by rdb$relation_name"
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+   # TODO: rdb$view_source is null for table and rdb$view_source is not null 
for view
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
+                          'type':'table',
+                        'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     statement = "select rdb$relation_name, rdb$view_source "+\
+                       "from rdb$relations " + \
+                       "where rdb$relation_name = '%s'" % (name)
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
+                            'type':'table',
+                          'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+   # Return a list of fields (for _buildDeleteStatement and for 
_buildUpdateStatement)
+   def __getPrimaryKey(self, relname):
+     statement = "select rdb$relation_name, rdb$field_name, "+\
+                                  "rdb$constraint_name, rdb$field_position "+\
+                                   "from rdb$relation_constraints rc, 
rdb$index_segments ri "+\
+                                   "where ri.rdb$index_name = 
rc.rdb$index_name "+\
+                                           "and rc.rdb$constraint_type = 
'PRIMARY KEY' "+\
+                                           "and rc.rdb$relation_name = '%s' " 
% (relname)+\
+                                   "order by ri.rdb$field_position"
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(lower(rstrip(rs[1])))
+ 
+     cursor.close()
+     return list
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "select * from %s"%(parent.name) + " where (0=1)"
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+ 
+     for d in cursor.description:
+       try:
+         nativetype = lower(d[SIG2api.DESCRIPTION_TYPE_CODE].__name__)
+       except AttributeError:
+         nativetype='unknown'
+       
+       attrs={'id':d[SIG2api.DESCRIPTION_NAME],
+                  'name':lower(d[SIG2api.DESCRIPTION_NAME]),
+                  'type':'field',
+                  'nativetype': nativetype,
+                  'required': d[SIG2api.DESCRIPTION_NULL_OK]==0,
+                  'length': d[SIG2api.DESCRIPTION_DISPLAY_SIZE]}
+ 
+       if nativetype in ('int','float','long'):
+         attrs['datatype']='number'
+         attrs['precision']=d[SIG2api.DESCRIPTION_SCALE]
+       elif nativetype == 'tuple':
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       cursor.execute("select rdb$default_source from rdb$relation_fields"+ \
+                   " where rdb$relation_name = '%s' " % (parent.name)+ \
+                   " and rdb$field_name = '%s'" % (upper(attrs['name'])))
+       defrs = cursor.fetchone()
+       if defrs[0]:
+         dflt = defrs[0]
+         if dflt[9:12] == "NOW":
+           attrs['defaulttype'] = 'timestamp'
+         else:
+           attrs['defaulttype'] = 'constant'
+           attrs['defaultval'] = dflt[8:]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self.native)
+ 
+ 
+ class DataObject_Object(DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail,\
+                                                 additionalSQL)
+ 
+ 
+ class DataObject_SQL(DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions, forDetail,\
+                                             additionalSQL)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select cast('now' as date) from rdb$database")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select gen_id(%s,1) from rdb$database" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except mesg:
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % mesg)
+       cursor.close()
+       return None
+ 
+     try:
+       return rv[0]
+     except:
+       return None
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': DataObject_Object,
+   'sql':    DataObject_SQL
+ }
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/interbase/interbase/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/interbase/interbase/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:50 2003
--- gnue-common/src/datasources/drivers/interbase/interbase/DataObject.py       
Thu Oct  9 21:21:19 2003
***************
*** 0 ****
--- 1,339 ----
+ #
+ # 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:
+ # interbase/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via the Kinterbasdb Interbase/Firebird 
Python Driver
+ # Requires Kinterbasdb > 3.0 (http://kinterbasdb.sourceforge.net/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the Interbase host for your connection  (required)
+ #     dbame=      This is the Interbase database to use (required)
+ #
+ 
+ 
+ 
+ from string import upper, lower, rstrip
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import kinterbasdb as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Kinterbasdb for Interbase [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Interbase_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Interbase_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Interbase_RecordSet
+ 
+ 
+ class Interbase_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Interbase_ResultSet
+     self._primaryKeyFields = []
+ 
+     # The date/time format used in insert/select statements
+     # (based on format used for time.strftime())
+     self._dateTimeFormat = "cast('%Y-%m-%d %H:%M:%S' as timestamp)"
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Interbase database driver initializing")
+ 
+     try:
+       charset = connectData['charset']
+     except KeyError:
+       charset = ""
+ 
+     try:
+       self._dataConnection = SIG2api.connect( \
+                  user=str(connectData['_username']), \
+                  password=str(connectData['_password']), \
+                  charset=charset, \
+                  database=connectData['dbname'], \
+                  host=connectData['host'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+   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)
+ 
+         #kinterbasdb 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
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+   # This excludes any system tables and views.
+     statement = "select rdb$relation_name, rdb$view_source "+\
+                       "from rdb$relations " + \
+                       "where rdb$system_flag=0 " + \
+                       "order by rdb$relation_name"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+   # TODO: rdb$view_source is null for table and rdb$view_source is not null 
for view
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
+                          'type':'table',
+                        'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     statement = "select rdb$relation_name, rdb$view_source "+\
+                       "from rdb$relations " + \
+                       "where rdb$relation_name = '%s'" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
+                            'type':'table',
+                          'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+   # Return a list of fields (for _buildDeleteStatement and for 
_buildUpdateStatement)
+   def __getPrimaryKey(self, relname):
+     statement = "select rdb$relation_name, rdb$field_name, "+\
+                                  "rdb$constraint_name, rdb$field_position "+\
+                                   "from rdb$relation_constraints rc, 
rdb$index_segments ri "+\
+                                   "where ri.rdb$index_name = 
rc.rdb$index_name "+\
+                                           "and rc.rdb$constraint_type = 
'PRIMARY KEY' "+\
+                                           "and rc.rdb$relation_name = '%s' " 
% (relname)+\
+                                   "order by ri.rdb$field_position"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(lower(rstrip(rs[1])))
+ 
+     cursor.close()
+     return list
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "select * from %s"%(parent.name) + " where (0=1)"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+ 
+     for d in cursor.description:
+       try:
+         nativetype = lower(d[SIG2api.DESCRIPTION_TYPE_CODE].__name__)
+       except AttributeError:
+         nativetype='unknown'
+       
+       attrs={'id':d[SIG2api.DESCRIPTION_NAME],
+                  'name':lower(d[SIG2api.DESCRIPTION_NAME]),
+                  'type':'field',
+                  'nativetype': nativetype,
+                  'required': d[SIG2api.DESCRIPTION_NULL_OK]==0,
+                  'length': d[SIG2api.DESCRIPTION_DISPLAY_SIZE]}
+ 
+       if nativetype in ('int','float','long'):
+         attrs['datatype']='number'
+         attrs['precision']=d[SIG2api.DESCRIPTION_SCALE]
+       elif nativetype == 'tuple':
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       cursor.execute("select rdb$default_source from rdb$relation_fields"+ \
+                   " where rdb$relation_name = '%s' " % (parent.name)+ \
+                   " and rdb$field_name = '%s'" % (upper(attrs['name'])))
+       defrs = cursor.fetchone()
+       if defrs[0]:
+         dflt = defrs[0]
+         if dflt[9:12] == "NOW":
+           attrs['defaulttype'] = 'timestamp'
+         else:
+           attrs['defaulttype'] = 'constant'
+           attrs['defaultval'] = dflt[8:]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Interbase_DataObject_Object(Interbase_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Interbase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail,\
+                                                 additionalSQL)
+ 
+ 
+ class Interbase_DataObject_SQL(Interbase_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Interbase_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Interbase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions, forDetail,\
+                                             additionalSQL)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select cast('now' as date) from rdb$database")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select gen_id(%s,1) from rdb$database" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except mesg:
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % mesg)
+       cursor.close()
+       return None
+ 
+     try:
+       return rv[0]
+     except:
+       return None
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Interbase_DataObject_Object,
+   'sql':    Interbase_DataObject_SQL
+ }
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/interbase/interbase/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/interbase/interbase/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:50 2003
--- gnue-common/src/datasources/drivers/interbase/interbase/RecordSet.py        
Thu Oct  9 21:21:19 2003
***************
*** 0 ****
--- 1,339 ----
+ #
+ # 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:
+ # interbase/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via the Kinterbasdb Interbase/Firebird 
Python Driver
+ # Requires Kinterbasdb > 3.0 (http://kinterbasdb.sourceforge.net/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the Interbase host for your connection  (required)
+ #     dbame=      This is the Interbase database to use (required)
+ #
+ 
+ 
+ 
+ from string import upper, lower, rstrip
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import kinterbasdb as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Kinterbasdb for Interbase [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Interbase_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Interbase_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Interbase_RecordSet
+ 
+ 
+ class Interbase_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Interbase_ResultSet
+     self._primaryKeyFields = []
+ 
+     # The date/time format used in insert/select statements
+     # (based on format used for time.strftime())
+     self._dateTimeFormat = "cast('%Y-%m-%d %H:%M:%S' as timestamp)"
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Interbase database driver initializing")
+ 
+     try:
+       charset = connectData['charset']
+     except KeyError:
+       charset = ""
+ 
+     try:
+       self._dataConnection = SIG2api.connect( \
+                  user=str(connectData['_username']), \
+                  password=str(connectData['_password']), \
+                  charset=charset, \
+                  database=connectData['dbname'], \
+                  host=connectData['host'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+   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)
+ 
+         #kinterbasdb 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
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+   # This excludes any system tables and views.
+     statement = "select rdb$relation_name, rdb$view_source "+\
+                       "from rdb$relations " + \
+                       "where rdb$system_flag=0 " + \
+                       "order by rdb$relation_name"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+   # TODO: rdb$view_source is null for table and rdb$view_source is not null 
for view
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
+                          'type':'table',
+                        'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     statement = "select rdb$relation_name, rdb$view_source "+\
+                       "from rdb$relations " + \
+                       "where rdb$relation_name = '%s'" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
+                            'type':'table',
+                          'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+   # Return a list of fields (for _buildDeleteStatement and for 
_buildUpdateStatement)
+   def __getPrimaryKey(self, relname):
+     statement = "select rdb$relation_name, rdb$field_name, "+\
+                                  "rdb$constraint_name, rdb$field_position "+\
+                                   "from rdb$relation_constraints rc, 
rdb$index_segments ri "+\
+                                   "where ri.rdb$index_name = 
rc.rdb$index_name "+\
+                                           "and rc.rdb$constraint_type = 
'PRIMARY KEY' "+\
+                                           "and rc.rdb$relation_name = '%s' " 
% (relname)+\
+                                   "order by ri.rdb$field_position"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(lower(rstrip(rs[1])))
+ 
+     cursor.close()
+     return list
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "select * from %s"%(parent.name) + " where (0=1)"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+ 
+     for d in cursor.description:
+       try:
+         nativetype = lower(d[SIG2api.DESCRIPTION_TYPE_CODE].__name__)
+       except AttributeError:
+         nativetype='unknown'
+       
+       attrs={'id':d[SIG2api.DESCRIPTION_NAME],
+                  'name':lower(d[SIG2api.DESCRIPTION_NAME]),
+                  'type':'field',
+                  'nativetype': nativetype,
+                  'required': d[SIG2api.DESCRIPTION_NULL_OK]==0,
+                  'length': d[SIG2api.DESCRIPTION_DISPLAY_SIZE]}
+ 
+       if nativetype in ('int','float','long'):
+         attrs['datatype']='number'
+         attrs['precision']=d[SIG2api.DESCRIPTION_SCALE]
+       elif nativetype == 'tuple':
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       cursor.execute("select rdb$default_source from rdb$relation_fields"+ \
+                   " where rdb$relation_name = '%s' " % (parent.name)+ \
+                   " and rdb$field_name = '%s'" % (upper(attrs['name'])))
+       defrs = cursor.fetchone()
+       if defrs[0]:
+         dflt = defrs[0]
+         if dflt[9:12] == "NOW":
+           attrs['defaulttype'] = 'timestamp'
+         else:
+           attrs['defaulttype'] = 'constant'
+           attrs['defaultval'] = dflt[8:]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Interbase_DataObject_Object(Interbase_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Interbase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail,\
+                                                 additionalSQL)
+ 
+ 
+ class Interbase_DataObject_SQL(Interbase_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Interbase_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Interbase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions, forDetail,\
+                                             additionalSQL)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select cast('now' as date) from rdb$database")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select gen_id(%s,1) from rdb$database" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except mesg:
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % mesg)
+       cursor.close()
+       return None
+ 
+     try:
+       return rv[0]
+     except:
+       return None
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Interbase_DataObject_Object,
+   'sql':    Interbase_DataObject_SQL
+ }
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/interbase/interbase/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/interbase/interbase/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:51 2003
--- gnue-common/src/datasources/drivers/interbase/interbase/ResultSet.py        
Thu Oct  9 21:21:19 2003
***************
*** 0 ****
--- 1,339 ----
+ #
+ # 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:
+ # interbase/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via the Kinterbasdb Interbase/Firebird 
Python Driver
+ # Requires Kinterbasdb > 3.0 (http://kinterbasdb.sourceforge.net/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the Interbase host for your connection  (required)
+ #     dbame=      This is the Interbase database to use (required)
+ #
+ 
+ 
+ 
+ from string import upper, lower, rstrip
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import kinterbasdb as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Kinterbasdb for Interbase [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Interbase_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Interbase_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Interbase_RecordSet
+ 
+ 
+ class Interbase_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Interbase_ResultSet
+     self._primaryKeyFields = []
+ 
+     # The date/time format used in insert/select statements
+     # (based on format used for time.strftime())
+     self._dateTimeFormat = "cast('%Y-%m-%d %H:%M:%S' as timestamp)"
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Interbase database driver initializing")
+ 
+     try:
+       charset = connectData['charset']
+     except KeyError:
+       charset = ""
+ 
+     try:
+       self._dataConnection = SIG2api.connect( \
+                  user=str(connectData['_username']), \
+                  password=str(connectData['_password']), \
+                  charset=charset, \
+                  database=connectData['dbname'], \
+                  host=connectData['host'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+   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)
+ 
+         #kinterbasdb 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
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+   # This excludes any system tables and views.
+     statement = "select rdb$relation_name, rdb$view_source "+\
+                       "from rdb$relations " + \
+                       "where rdb$system_flag=0 " + \
+                       "order by rdb$relation_name"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+   # TODO: rdb$view_source is null for table and rdb$view_source is not null 
for view
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
+                          'type':'table',
+                        'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     statement = "select rdb$relation_name, rdb$view_source "+\
+                       "from rdb$relations " + \
+                       "where rdb$relation_name = '%s'" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
+                            'type':'table',
+                          'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+   # Return a list of fields (for _buildDeleteStatement and for 
_buildUpdateStatement)
+   def __getPrimaryKey(self, relname):
+     statement = "select rdb$relation_name, rdb$field_name, "+\
+                                  "rdb$constraint_name, rdb$field_position "+\
+                                   "from rdb$relation_constraints rc, 
rdb$index_segments ri "+\
+                                   "where ri.rdb$index_name = 
rc.rdb$index_name "+\
+                                           "and rc.rdb$constraint_type = 
'PRIMARY KEY' "+\
+                                           "and rc.rdb$relation_name = '%s' " 
% (relname)+\
+                                   "order by ri.rdb$field_position"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(lower(rstrip(rs[1])))
+ 
+     cursor.close()
+     return list
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "select * from %s"%(parent.name) + " where (0=1)"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+ 
+     for d in cursor.description:
+       try:
+         nativetype = lower(d[SIG2api.DESCRIPTION_TYPE_CODE].__name__)
+       except AttributeError:
+         nativetype='unknown'
+       
+       attrs={'id':d[SIG2api.DESCRIPTION_NAME],
+                  'name':lower(d[SIG2api.DESCRIPTION_NAME]),
+                  'type':'field',
+                  'nativetype': nativetype,
+                  'required': d[SIG2api.DESCRIPTION_NULL_OK]==0,
+                  'length': d[SIG2api.DESCRIPTION_DISPLAY_SIZE]}
+ 
+       if nativetype in ('int','float','long'):
+         attrs['datatype']='number'
+         attrs['precision']=d[SIG2api.DESCRIPTION_SCALE]
+       elif nativetype == 'tuple':
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       cursor.execute("select rdb$default_source from rdb$relation_fields"+ \
+                   " where rdb$relation_name = '%s' " % (parent.name)+ \
+                   " and rdb$field_name = '%s'" % (upper(attrs['name'])))
+       defrs = cursor.fetchone()
+       if defrs[0]:
+         dflt = defrs[0]
+         if dflt[9:12] == "NOW":
+           attrs['defaulttype'] = 'timestamp'
+         else:
+           attrs['defaulttype'] = 'constant'
+           attrs['defaultval'] = dflt[8:]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Interbase_DataObject_Object(Interbase_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Interbase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail,\
+                                                 additionalSQL)
+ 
+ 
+ class Interbase_DataObject_SQL(Interbase_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Interbase_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Interbase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions, forDetail,\
+                                             additionalSQL)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select cast('now' as date) from rdb$database")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select gen_id(%s,1) from rdb$database" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except mesg:
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % mesg)
+       cursor.close()
+       return None
+ 
+     try:
+       return rv[0]
+     except:
+       return None
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Interbase_DataObject_Object,
+   'sql':    Interbase_DataObject_SQL
+ }
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/interbase/interbase/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/interbase/interbase/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:51 2003
--- gnue-common/src/datasources/drivers/interbase/interbase/__init__.py Thu Oct 
 9 21:21:19 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("Interbase Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: 
gnue-common/src/datasources/drivers/mysql/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/mysql/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:51 2003
--- gnue-common/src/datasources/drivers/mysql/Schema/Discovery/Introspection.py 
Thu Oct  9 21:21:20 2003
***************
*** 0 ****
--- 1,178 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     # TODO: This excludes any system tables and views. Should it?
+     statement = "SHOW TABLES"
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rs[0],
+                          'type':'table',
+                          'primarykey': self.__getPrimaryKey(rs[0])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "DESCRIBE %s" % (name)
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':name, 'name':name,
+                            'type':'table',
+                            'primarykey': self.__getPrimaryKey(name,cursor)},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   def __getPrimaryKey(self, id, cursor=None):
+     statement = "DESCRIBE %s" % id
+     if not cursor:
+       cursor = self.native.cursor()
+       close_cursor = 1
+     else:
+       close_cursor = 0
+     cursor.execute(statement)
+ 
+     lst = []
+     for rs in cursor.fetchall():
+       if rs[3] == 'PRI':
+         lst.append(rs[0])
+ 
+     if close_cursor:
+       cursor.close()
+ 
+     return tuple(lst)
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "DESCRIBE %s" % parent.id
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       nativetype = string.split(string.replace(rs[1],')',''),'(')
+ 
+ 
+       attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
+              'type':'field', 'nativetype': nativetype[0],
+              'required': rs[2] != 'YES'}
+ 
+       if nativetype[0] in ('int','integer','bigint','mediumint',
+                            'smallint','tinyint','float','real',
+                            'double','decimal'):
+         attrs['datatype']='number'
+       elif nativetype[0] in ('date','time','timestamp','datetime'):
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       try:
+         if len(nativetype) == 2:
+           try:
+             ln, prec = nativetype[1].split(',')
+           except:
+             ln = nativetype[1]
+             prec = None
+           attrs['length'] = int(ln.split()[0])
+           if prec != None:
+             attrs['precision'] = int(prec)
+       except ValueError:
+         GDebug.printMesg(1,'WARNING: mysql native type error: %s' % 
nativetype)
+ 
+       if rs[4] not in ('NULL', '0000-00-00 00:00:00','', None):
+         attrs['defaulttype'] = 'constant'
+         attrs['defaultval'] = rs[4]
+ 
+       if rs[5] == 'auto_increment':
+         attrs['defaulttype'] = 'serial'
+ 
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
Index: gnue-common/src/datasources/drivers/mysql/mysql/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/mysql/mysql/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:51 2003
--- gnue-common/src/datasources/drivers/mysql/mysql/Connection.py       Thu Oct 
 9 21:21:21 2003
***************
*** 0 ****
--- 1,96 ----
+ #
+ # 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:
+ # mysql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data vi MySQL
+ #
+ # NOTES:
+ # Supports transactions if the MySQL server is compiled w/transaction support
+ # (which it does NOT by default)
+ 
+ __all__ = ['Connection']
+ 
+ import string
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ from DataObject import *
+ from gnue.common.datasources.drivers.mysql.Schema.Discovery.Introspection 
import Introspection
+ 
+ try:
+   import MySQLdb
+ except ImportError, message:
+   tmsg = _("Driver not installed: sapdbapi for SAP-DB 7.x \n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ ######################################################################
+ #
+ #  GConnection object for PostgreSQL-based drivers
+ #
+ class Connection(DBSIG2.Connection):
+ 
+   _defaultBehavior = Introspection
+   _DatabaseError = MySQLdb.DatabaseError
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+   self._mysql = MySQLdb
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Mysql database driver initializing")
+ 
+     try:
+       self.native = MySQLdb.connect(user=connectData['_username'],
+                    passwd=connectData['_password'],
+                    host=connectData['host'],
+                    db=connectData['dbname'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._beginTransaction()
+ 
+ 
+   def _beginTransaction(self):
+     try:
+       self.native.begin()
+     except:
+       pass
+ 
+ 
+ 
+ # Return the current date, according to database
+ #  def getDate(self):
+ #    pass
+ 
+   # Return a sequence number from sequence 'name'
+ #  def getSequence(self, name):
+ #    pass
+ 
+   # Run the SQL statement 'statement'
+ #  def sql(self, statement):
+ #    pass
+ 
Index: gnue-common/src/datasources/drivers/mysql/mysql/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/mysql/mysql/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:51 2003
--- gnue-common/src/datasources/drivers/mysql/mysql/DataObject.py       Thu Oct 
 9 21:21:21 2003
***************
*** 0 ****
--- 1,323 ----
+ #
+ # 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:
+ # mysql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data vi MySQL
+ #
+ # NOTES:
+ # Supports transactions if the MySQL server is compiled w/transaction support
+ # (which it does NOT by default)
+ 
+ 
+ import string
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import MySQLdb
+ except ImportError, mesg:
+   GDebug.printMesg(1,mesg)
+   print "-"*79
+   print _("\nCould not load MySQLdb.  For MySQL support, please install \n") \
+       + _("mysql-python 0.9.0 or later from") \
+       + "http://sourceforge.net/projects/mysql-python\n";
+   print _("Error:  %s") % mesg
+   print "-"*79
+   sys.exit()
+ 
+ 
+ 
+ class MySQL_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class MySQL_ResultSet(DBSIG2.ResultSet): 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None): 
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = MySQL_RecordSet
+ 
+     # Compensate for bug in python mysql drivers older than 0.9.2a2
+     if MySQLdb.__version__ >= '0.9.2a2':
+       self.fetchBugFix = self._cursor.fetchmany
+     else:
+       self.__done = 0
+       self.fetchBugFix = self.__mySqlNeedsLotsOfTLC
+ 
+   
+   # Compensate for MySQ bug
+   def __mySqlNeedsLotsOfTLC(self):
+     if self.__done:
+       return None
+ 
+     self.__done = 1
+     return self._cursor.fetchall()
+ 
+ 
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         # See __init__ for details
+       rsets = self.fetchBugFix()
+ 
+       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:
+         return 0
+     else:
+      return 0
+ 
+ class MySQL_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = MySQLdb.DatabaseError
+     self._resultSetClass = MySQL_ResultSet
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Mysql database driver initializing")
+ 
+     try:
+       self._dataConnection = MySQLdb.connect(user=connectData['_username'],
+                    passwd=connectData['_password'],
+                    host=connectData['host'],
+                    db=connectData['dbname'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._beginTransaction()
+     self._postConnect()
+ 
+ 
+   def _postConnect(self): 
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   def _beginTransaction(self):
+     try:
+       self._dataConnection.begin()
+     except: 
+       pass
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     # TODO: This excludes any system tables and views. Should it?
+     statement = "SHOW TABLES"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rs[0],
+                          'type':'table',
+                          'primarykey': self.__getPrimaryKey(rs[0])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "DESCRIBE %s" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':name, 'name':name,
+                            'type':'table',
+                            'primarykey': self.__getPrimaryKey(name,cursor)},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   def __getPrimaryKey(self, id, cursor=None):
+     statement = "DESCRIBE %s" % id
+     if not cursor:
+       cursor = self._dataConnection.cursor()
+       close_cursor = 1
+     else:
+       close_cursor = 0
+     cursor.execute(statement)
+ 
+     lst = []
+     for rs in cursor.fetchall():
+       if rs[3] == 'PRI':
+         lst.append(rs[0])
+ 
+     if close_cursor:
+       cursor.close()
+ 
+     return tuple(lst)
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "DESCRIBE %s" % parent.id
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       nativetype = string.split(string.replace(rs[1],')',''),'(')
+ 
+ 
+       attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
+              'type':'field', 'nativetype': nativetype[0],
+              'required': rs[2] != 'YES'}
+ 
+       if nativetype[0] in ('int','integer','bigint','mediumint',
+                            'smallint','tinyint','float','real',
+                            'double','decimal'):
+         attrs['datatype']='number'
+       elif nativetype[0] in ('date','time','timestamp','datetime'):
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       try:
+         if len(nativetype) == 2:
+           try:
+             ln, prec = nativetype[1].split(',')
+           except:
+             ln = nativetype[1]
+             prec = None
+           attrs['length'] = int(ln.split()[0])
+           if prec != None:
+             attrs['precision'] = int(prec)
+       except ValueError:
+         GDebug.printMesg(1,'WARNING: mysql native type error: %s' % 
nativetype)
+ 
+       if rs[4] not in ('NULL', '0000-00-00 00:00:00','', None):
+         attrs['defaulttype'] = 'constant'
+         attrs['defaultval'] = rs[4]
+ 
+       if rs[5] == 'auto_increment':
+         attrs['defaulttype'] = 'serial'
+ 
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+ 
+ 
+ 
+ class MySQL_DataObject_Object(MySQL_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     MySQL_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class MySQL_DataObject_SQL(MySQL_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because MySQL_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     MySQL_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #  
+ class TriggerExtensions: 
+ 
+   def __init__(self, connection): 
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+ #  def getDate(self): 
+ #    pass
+ 
+   # Return a sequence number from sequence 'name' 
+ #  def getSequence(self, name): 
+ #    pass
+ 
+   # Run the SQL statement 'statement'
+ #  def sql(self, statement): 
+ #    pass
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe 
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ # 
+ supportedDataObjects = {
+   'object': MySQL_DataObject_Object,
+   'sql':    MySQL_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/mysql/mysql/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/mysql/mysql/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:52 2003
--- gnue-common/src/datasources/drivers/mysql/mysql/RecordSet.py        Thu Oct 
 9 21:21:21 2003
***************
*** 0 ****
--- 1,323 ----
+ #
+ # 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:
+ # mysql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data vi MySQL
+ #
+ # NOTES:
+ # Supports transactions if the MySQL server is compiled w/transaction support
+ # (which it does NOT by default)
+ 
+ 
+ import string
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import MySQLdb
+ except ImportError, mesg:
+   GDebug.printMesg(1,mesg)
+   print "-"*79
+   print _("\nCould not load MySQLdb.  For MySQL support, please install \n") \
+       + _("mysql-python 0.9.0 or later from") \
+       + "http://sourceforge.net/projects/mysql-python\n";
+   print _("Error:  %s") % mesg
+   print "-"*79
+   sys.exit()
+ 
+ 
+ 
+ class MySQL_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class MySQL_ResultSet(DBSIG2.ResultSet): 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None): 
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = MySQL_RecordSet
+ 
+     # Compensate for bug in python mysql drivers older than 0.9.2a2
+     if MySQLdb.__version__ >= '0.9.2a2':
+       self.fetchBugFix = self._cursor.fetchmany
+     else:
+       self.__done = 0
+       self.fetchBugFix = self.__mySqlNeedsLotsOfTLC
+ 
+   
+   # Compensate for MySQ bug
+   def __mySqlNeedsLotsOfTLC(self):
+     if self.__done:
+       return None
+ 
+     self.__done = 1
+     return self._cursor.fetchall()
+ 
+ 
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         # See __init__ for details
+       rsets = self.fetchBugFix()
+ 
+       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:
+         return 0
+     else:
+      return 0
+ 
+ class MySQL_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = MySQLdb.DatabaseError
+     self._resultSetClass = MySQL_ResultSet
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Mysql database driver initializing")
+ 
+     try:
+       self._dataConnection = MySQLdb.connect(user=connectData['_username'],
+                    passwd=connectData['_password'],
+                    host=connectData['host'],
+                    db=connectData['dbname'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._beginTransaction()
+     self._postConnect()
+ 
+ 
+   def _postConnect(self): 
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   def _beginTransaction(self):
+     try:
+       self._dataConnection.begin()
+     except: 
+       pass
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     # TODO: This excludes any system tables and views. Should it?
+     statement = "SHOW TABLES"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rs[0],
+                          'type':'table',
+                          'primarykey': self.__getPrimaryKey(rs[0])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "DESCRIBE %s" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':name, 'name':name,
+                            'type':'table',
+                            'primarykey': self.__getPrimaryKey(name,cursor)},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   def __getPrimaryKey(self, id, cursor=None):
+     statement = "DESCRIBE %s" % id
+     if not cursor:
+       cursor = self._dataConnection.cursor()
+       close_cursor = 1
+     else:
+       close_cursor = 0
+     cursor.execute(statement)
+ 
+     lst = []
+     for rs in cursor.fetchall():
+       if rs[3] == 'PRI':
+         lst.append(rs[0])
+ 
+     if close_cursor:
+       cursor.close()
+ 
+     return tuple(lst)
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "DESCRIBE %s" % parent.id
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       nativetype = string.split(string.replace(rs[1],')',''),'(')
+ 
+ 
+       attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
+              'type':'field', 'nativetype': nativetype[0],
+              'required': rs[2] != 'YES'}
+ 
+       if nativetype[0] in ('int','integer','bigint','mediumint',
+                            'smallint','tinyint','float','real',
+                            'double','decimal'):
+         attrs['datatype']='number'
+       elif nativetype[0] in ('date','time','timestamp','datetime'):
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       try:
+         if len(nativetype) == 2:
+           try:
+             ln, prec = nativetype[1].split(',')
+           except:
+             ln = nativetype[1]
+             prec = None
+           attrs['length'] = int(ln.split()[0])
+           if prec != None:
+             attrs['precision'] = int(prec)
+       except ValueError:
+         GDebug.printMesg(1,'WARNING: mysql native type error: %s' % 
nativetype)
+ 
+       if rs[4] not in ('NULL', '0000-00-00 00:00:00','', None):
+         attrs['defaulttype'] = 'constant'
+         attrs['defaultval'] = rs[4]
+ 
+       if rs[5] == 'auto_increment':
+         attrs['defaulttype'] = 'serial'
+ 
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+ 
+ 
+ 
+ class MySQL_DataObject_Object(MySQL_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     MySQL_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class MySQL_DataObject_SQL(MySQL_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because MySQL_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     MySQL_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #  
+ class TriggerExtensions: 
+ 
+   def __init__(self, connection): 
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+ #  def getDate(self): 
+ #    pass
+ 
+   # Return a sequence number from sequence 'name' 
+ #  def getSequence(self, name): 
+ #    pass
+ 
+   # Run the SQL statement 'statement'
+ #  def sql(self, statement): 
+ #    pass
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe 
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ # 
+ supportedDataObjects = {
+   'object': MySQL_DataObject_Object,
+   'sql':    MySQL_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/mysql/mysql/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/mysql/mysql/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:52 2003
--- gnue-common/src/datasources/drivers/mysql/mysql/ResultSet.py        Thu Oct 
 9 21:21:21 2003
***************
*** 0 ****
--- 1,323 ----
+ #
+ # 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:
+ # mysql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data vi MySQL
+ #
+ # NOTES:
+ # Supports transactions if the MySQL server is compiled w/transaction support
+ # (which it does NOT by default)
+ 
+ 
+ import string
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import MySQLdb
+ except ImportError, mesg:
+   GDebug.printMesg(1,mesg)
+   print "-"*79
+   print _("\nCould not load MySQLdb.  For MySQL support, please install \n") \
+       + _("mysql-python 0.9.0 or later from") \
+       + "http://sourceforge.net/projects/mysql-python\n";
+   print _("Error:  %s") % mesg
+   print "-"*79
+   sys.exit()
+ 
+ 
+ 
+ class MySQL_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class MySQL_ResultSet(DBSIG2.ResultSet): 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None): 
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = MySQL_RecordSet
+ 
+     # Compensate for bug in python mysql drivers older than 0.9.2a2
+     if MySQLdb.__version__ >= '0.9.2a2':
+       self.fetchBugFix = self._cursor.fetchmany
+     else:
+       self.__done = 0
+       self.fetchBugFix = self.__mySqlNeedsLotsOfTLC
+ 
+   
+   # Compensate for MySQ bug
+   def __mySqlNeedsLotsOfTLC(self):
+     if self.__done:
+       return None
+ 
+     self.__done = 1
+     return self._cursor.fetchall()
+ 
+ 
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         # See __init__ for details
+       rsets = self.fetchBugFix()
+ 
+       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:
+         return 0
+     else:
+      return 0
+ 
+ class MySQL_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = MySQLdb.DatabaseError
+     self._resultSetClass = MySQL_ResultSet
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Mysql database driver initializing")
+ 
+     try:
+       self._dataConnection = MySQLdb.connect(user=connectData['_username'],
+                    passwd=connectData['_password'],
+                    host=connectData['host'],
+                    db=connectData['dbname'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._beginTransaction()
+     self._postConnect()
+ 
+ 
+   def _postConnect(self): 
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   def _beginTransaction(self):
+     try:
+       self._dataConnection.begin()
+     except: 
+       pass
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     # TODO: This excludes any system tables and views. Should it?
+     statement = "SHOW TABLES"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rs[0],
+                          'type':'table',
+                          'primarykey': self.__getPrimaryKey(rs[0])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "DESCRIBE %s" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':name, 'name':name,
+                            'type':'table',
+                            'primarykey': self.__getPrimaryKey(name,cursor)},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   def __getPrimaryKey(self, id, cursor=None):
+     statement = "DESCRIBE %s" % id
+     if not cursor:
+       cursor = self._dataConnection.cursor()
+       close_cursor = 1
+     else:
+       close_cursor = 0
+     cursor.execute(statement)
+ 
+     lst = []
+     for rs in cursor.fetchall():
+       if rs[3] == 'PRI':
+         lst.append(rs[0])
+ 
+     if close_cursor:
+       cursor.close()
+ 
+     return tuple(lst)
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "DESCRIBE %s" % parent.id
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       nativetype = string.split(string.replace(rs[1],')',''),'(')
+ 
+ 
+       attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
+              'type':'field', 'nativetype': nativetype[0],
+              'required': rs[2] != 'YES'}
+ 
+       if nativetype[0] in ('int','integer','bigint','mediumint',
+                            'smallint','tinyint','float','real',
+                            'double','decimal'):
+         attrs['datatype']='number'
+       elif nativetype[0] in ('date','time','timestamp','datetime'):
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       try:
+         if len(nativetype) == 2:
+           try:
+             ln, prec = nativetype[1].split(',')
+           except:
+             ln = nativetype[1]
+             prec = None
+           attrs['length'] = int(ln.split()[0])
+           if prec != None:
+             attrs['precision'] = int(prec)
+       except ValueError:
+         GDebug.printMesg(1,'WARNING: mysql native type error: %s' % 
nativetype)
+ 
+       if rs[4] not in ('NULL', '0000-00-00 00:00:00','', None):
+         attrs['defaulttype'] = 'constant'
+         attrs['defaultval'] = rs[4]
+ 
+       if rs[5] == 'auto_increment':
+         attrs['defaulttype'] = 'serial'
+ 
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+ 
+ 
+ 
+ class MySQL_DataObject_Object(MySQL_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     MySQL_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class MySQL_DataObject_SQL(MySQL_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because MySQL_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     MySQL_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #  
+ class TriggerExtensions: 
+ 
+   def __init__(self, connection): 
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+ #  def getDate(self): 
+ #    pass
+ 
+   # Return a sequence number from sequence 'name' 
+ #  def getSequence(self, name): 
+ #    pass
+ 
+   # Run the SQL statement 'statement'
+ #  def sql(self, statement): 
+ #    pass
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe 
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ # 
+ supportedDataObjects = {
+   'object': MySQL_DataObject_Object,
+   'sql':    MySQL_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/mysql/mysql/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/mysql/mysql/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:52 2003
--- gnue-common/src/datasources/drivers/mysql/mysql/__init__.py Thu Oct  9 
21:21:21 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("MySQL Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/odbc/__init__.py
diff -c /dev/null gnue-common/src/datasources/drivers/odbc/__init__.py:1.2.2.1
*** /dev/null   Thu Oct  9 21:21:52 2003
--- gnue-common/src/datasources/drivers/odbc/__init__.py        Thu Oct  9 
21:21:21 2003
***************
*** 0 ****
--- 1 ----
+ DRIVERS=['wodbc']
Index: gnue-common/src/datasources/drivers/odbc/wodbc/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/odbc/wodbc/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:54 2003
--- gnue-common/src/datasources/drivers/odbc/wodbc/Connection.py        Thu Oct 
 9 21:21:22 2003
***************
*** 0 ****
--- 1,477 ----
+ #
+ # 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:
+ # odbc/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via the public domain win32all ODBC Driver
+ #
+ # NOTES:
+ # Only works under Win32... requires the win32all extensions.
+ # 
(http://aspn.activestate.com/ASPN/Downloads/ActivePython/Extensions/Win32all)
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=   This is the ODBC DSN= string to use.
+ #
+ #
+ 
+ __all__ = ['Connection']
+ 
+ import sys, string, types
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ 
+ 
+ try:
+   import dbi, odbc
+ except ImportError, message:
+   tmsg = _("Driver not installed: win32all ODBC driver\n\n[%s") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ 
+ 
+ class ODBC_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 = {}
+         for key in self._fields.keys():
+           self._initialData[key] = self._fields[key]
+ 
+     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._primaryIdField):
+       where = [self._parent._primaryIdFormat % \
+           self._initialData[self._parent._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._initialData[field]))
+ 
+     statement = "DELETE FROM %s WHERE %s" % \
+        (self._parent._dataObject.table, string.join(where,' AND ') )
+     return statement
+ 
+   def _buildInsertStatement(self): 
+     vals = []
+     fields = []
+ 
+     # TODO: This should actually only insert modified fields.
+     # TODO: Unfortunately, self._modifiedFlags is not being 
+     # TODO: set for new records (address@hidden)
+     #for field in self._modifiedFlags.keys():
+ 
+     for field in self._fields.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:
+           try: 
+             if self._parent._fieldTypes[field] == 'number': 
+               vals.append ("%s" % (self._fields[field]))
+             else: 
+               vals.append ("'%s'" % (self._fields[field]))
+           except ValueError:
+             vals.append ("%s" % (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():
+       try:
+         if self._parent._fieldTypes[field] == 'number':
+           updates.append ("%s=%s" % (field, self._fields[field]))
+         else:
+           updates.append ("%s='%s'" % (field, self._fields[field]))
+       except KeyError:
+         updates.append ("%s='%s'" % (field, self._fields[field]))
+ 
+     if self._initialData.has_key(self._parent._primaryIdField):
+       where = [self._parent._primaryIdFormat % \
+           self._initialData[self._parent._primaryIdField]  ]
+     else:
+       where = []
+       for field in self._initialData.keys():
+         if self._initialData[field] == None:
+           where.append ("%s IS NULL" % field)
+         else:
+           try:
+             if self._parent._fieldTypes[field] == 'number':
+               where.append ("%s=%s" % (field, self._initialData[field]))
+             else:
+               where.append ("%s='%s'" % (field, self._initialData[field]))
+           except KeyError:
+             where.append ("%s='%s'" % (field, self._initialData[field]))
+ 
+     return "UPDATE %s SET %s WHERE %s" % \
+        (self._parent._dataObject.table, string.join(updates,','), \
+         string.join(where,' AND ') )
+ 
+ 
+ class ODBC_ResultSet(GDataObjects.ResultSet): 
+   def __init__(self, dataObject, cursor=None, \
+         defaultValues={}, masterRecordSet=None):
+     GDataObjects.ResultSet.__init__(
+            self,dataObject,cursor,defaultValues,masterRecordSet)
+     self._recordSetClass = ODBC_RecordSet
+     self._fieldNames = None
+     self._fieldTypes = {}
+ 
+ #    self._recordCount = cursor.rowcount > 0 and cursor.rowcount or 0
+     self._recordCount = 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.
+     self._primaryIdField = None
+     self._primaryIdFormat = "__gnue__ = '%s'"
+ 
+     GDebug.printMesg(5, 'ResultSet created')
+ 
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         rs = self._cursor.fetchone()
+       except self._dataObject._DatabaseError, err:
+         pass
+ # TODO: It seems that popy does what the other drivers don't
+ # TODO: and raises this error ALOT need to find out why
+ #        raise GDataObjects.ConnectionError, err
+ 
+       if rs:
+         if not self._fieldNames:
+           self._fieldNames = []
+           for t in (self._cursor.description):
+             self._fieldNames.append (string.lower(t[0]))
+             self._fieldTypes[string.lower(t[0])] = (string.lower(t[1]))
+         i = 0
+         dict = {}
+         for f in (rs):
+           dict[self._fieldNames[i]] = f
+           i = i + 1
+         self._cachedRecords.append (self._recordSetClass(parent=self, \
+                                             initialData=dict))
+         return 1
+       else:
+         return 0
+     else:
+       return 0
+ 
+ 
+ class ODBC_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     ),
+        '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     ) }
+ 
+   def __init__(self, strictQueryCount=1):
+     GDataObjects.DataObject.__init__(self)
+ 
+     GDebug.printMesg (1,"DB-SIG database driver backend initializing")
+ 
+     self._resultSetClass = ODBC_ResultSet
+     self._DatabaseError = None
+     self._strictQueryCount = strictQueryCount
+ 
+ 
+   # This should be over-ridden only if driver needs more than user/pass
+   def getLoginFields(self):
+     return [['_username', 'User Name',0],['_password', 'Password',1]]
+ 
+ 
+   def connect(self, connectData={}):
+ 
+     GDebug.printMesg(1,"ODBC database driver initializing")
+     self._DatabaseError = odbc.error
+ 
+     try:
+       service = connectData['service']
+     except KeyError:
+       service = ""
+ 
+     try:
+       self.native = odbc.odbc( "%s/%s/%s" % (
+                    service,
+                    connectData['_username'],
+                    connectData['_password']))
+ 
+     except dbi.opError, value:
+       raise GDataObjects.LoginError, value
+ 
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return None # [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self.native)
+ 
+   def _createResultSet(self, conditions={}, readOnly=0, 
masterRecordSet=None,sql=""):
+     try:
+       cursor = self.native.cursor()
+       cursor.execute(self._buildQuery(conditions))
+ 
+     except dbi.progError, err:
+       raise GDataObjects.ConnectionError, err
+ 
+     except self._DatabaseError, err:
+       raise GDataObjects.ConnectionError, err
+     rs = self._resultSetClass(self, cursor=cursor, 
masterRecordSet=masterRecordSet)
+ 
+     # pull a record count for the upcomming query
+     if self._strictQueryCount:
+       rs._recordCount = self._getQueryCount(conditions)
+ 
+     if readOnly:
+       rs._readonly = readOnly
+     return rs
+ 
+ 
+   def _getQueryCount(self,conditions={}):
+     cursor = self.native.cursor()
+ 
+     cursor.execute(self._buildQueryCount(conditions))
+     rs = cursor.fetchone()
+     return int(rs[0])
+ 
+     
+   def _buildQueryCount(self, conditions={}):
+     q = "SELECT count(*) FROM %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+   def commit(self):
+     GDebug.printMesg (5,"DB-SIG database driver: commit()")
+ 
+     try: 
+       self.native.commit()
+     except self._DatabaseError, value:
+       raise GDataObjects.ConnectionError, value
+     
+     self._beginTransaction()
+ 
+   def rollback(self): 
+     GDebug.printMesg (5,"DB-SIG database driver: rollback()")
+ 
+     try: 
+       self.native.rollback()
+     except: 
+       pass    # I'm SURE this isn't right (jcater)
+                 # But not all db's support transactions
+ 
+     self._beginTransaction()
+ 
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return None
+ 
+ 
+   # 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
+   def __conditionToSQL (self, element): 
+     if type(element) != types.InstanceType: 
+       return "%s" % element
+     else: 
+       otype = string.lower(element._type[2:])
+       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 "'%s'" % element.value
+       elif otype == 'param':
+         v = element.getValue()
+         return (v == None and "NULL") or ("'%s'" % element.getValue())
+       elif self.conditionElements.has_key(otype):
+         for i in range(0, len(element._children)): 
+           element._children[i] = self.__conditionToSQL(element._children[i])
+         if len(element._children) < self.conditionElements[otype][0]: 
+           tmsg = _('Condition element "%s" expects at least %s arguments; 
found %s') % \
+                 (otype, self.conditionElements[otype][0], 
len(element._children))
+           raise GConditions.ConditionError, tmsg
+         if len(element._children) > self.conditionElements[otype][1]: 
+           tmsg = _('Condition element "%s" expects at most %s arguments; 
found %s') % \
+                 (otype, self.conditionElements[otype][0], 
len(element._children))
+           raise GConditions.ConditionError, tmsg
+         if self.conditionElements[otype][3] == None: 
+           return self.conditionElements[otype][2] % tuple(element._children)
+         else: 
+           return self.conditionElements[otype][2] % \
+             (string.join(element._children, 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      
+ 
+ 
+ class ODBC_DataObject_Object(ODBC_DataObject): 
+   def _buildQuery(self, conditions={}): 
+     GDebug.printMesg(7,'Implicit Fields: %s' % self._fieldReferences)
+     if len(self._fieldReferences):
+       q = "SELECT %s FROM %s%s" % \
+            (string.join(self._fieldReferences.keys(),","), self.table, 
+             self._conditionToSQL(conditions))
+     else: 
+       q = "SELECT * FROM %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     if hasattr(self,'order_by'):
+      q = "%s ORDER BY %s " % (q, self.order_by)
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': ODBC_DataObject_Object,
+ #  'sql':    ODBC_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/odbc/wodbc/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/odbc/wodbc/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:54 2003
--- gnue-common/src/datasources/drivers/odbc/wodbc/DataObject.py        Thu Oct 
 9 21:21:22 2003
***************
*** 0 ****
--- 1,476 ----
+ #
+ # 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:
+ # odbc/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via the public domain win32all ODBC Driver
+ #
+ # NOTES:
+ # Only works under Win32... requires the win32all extensions.
+ # 
(http://aspn.activestate.com/ASPN/Downloads/ActivePython/Extensions/Win32all)
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=   This is the ODBC DSN= string to use.
+ #
+ #
+ 
+ 
+ import sys, string, types
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ 
+ 
+ try:
+   import dbi, odbc
+ except ImportError, message:
+   tmsg = _("Driver not installed: win32all ODBC driver\n\n[%s") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ 
+ 
+ class ODBC_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 = {}
+         for key in self._fields.keys():
+           self._initialData[key] = self._fields[key]
+ 
+     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._primaryIdField):
+       where = [self._parent._primaryIdFormat % \
+           self._initialData[self._parent._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._initialData[field]))
+ 
+     statement = "DELETE FROM %s WHERE %s" % \
+        (self._parent._dataObject.table, string.join(where,' AND ') )
+     return statement
+ 
+   def _buildInsertStatement(self): 
+     vals = []
+     fields = []
+ 
+     # TODO: This should actually only insert modified fields.
+     # TODO: Unfortunately, self._modifiedFlags is not being 
+     # TODO: set for new records (address@hidden)
+     #for field in self._modifiedFlags.keys():
+ 
+     for field in self._fields.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:
+           try: 
+             if self._parent._fieldTypes[field] == 'number': 
+               vals.append ("%s" % (self._fields[field]))
+             else: 
+               vals.append ("'%s'" % (self._fields[field]))
+           except ValueError:
+             vals.append ("%s" % (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():
+       try:
+         if self._parent._fieldTypes[field] == 'number':
+           updates.append ("%s=%s" % (field, self._fields[field]))
+         else:
+           updates.append ("%s='%s'" % (field, self._fields[field]))
+       except KeyError:
+         updates.append ("%s='%s'" % (field, self._fields[field]))
+ 
+     if self._initialData.has_key(self._parent._primaryIdField):
+       where = [self._parent._primaryIdFormat % \
+           self._initialData[self._parent._primaryIdField]  ]
+     else:
+       where = []
+       for field in self._initialData.keys():
+         if self._initialData[field] == None:
+           where.append ("%s IS NULL" % field)
+         else:
+           try:
+             if self._parent._fieldTypes[field] == 'number':
+               where.append ("%s=%s" % (field, self._initialData[field]))
+             else:
+               where.append ("%s='%s'" % (field, self._initialData[field]))
+           except KeyError:
+             where.append ("%s='%s'" % (field, self._initialData[field]))
+ 
+     return "UPDATE %s SET %s WHERE %s" % \
+        (self._parent._dataObject.table, string.join(updates,','), \
+         string.join(where,' AND ') )
+ 
+ 
+ class ODBC_ResultSet(GDataObjects.ResultSet): 
+   def __init__(self, dataObject, cursor=None, \
+         defaultValues={}, masterRecordSet=None):
+     GDataObjects.ResultSet.__init__(
+            self,dataObject,cursor,defaultValues,masterRecordSet)
+     self._recordSetClass = ODBC_RecordSet
+     self._fieldNames = None
+     self._fieldTypes = {}
+ 
+ #    self._recordCount = cursor.rowcount > 0 and cursor.rowcount or 0
+     self._recordCount = 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.
+     self._primaryIdField = None
+     self._primaryIdFormat = "__gnue__ = '%s'"
+ 
+     GDebug.printMesg(5, 'ResultSet created')
+ 
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         rs = self._cursor.fetchone()
+       except self._dataObject._DatabaseError, err:
+         pass
+ # TODO: It seems that popy does what the other drivers don't
+ # TODO: and raises this error ALOT need to find out why
+ #        raise GDataObjects.ConnectionError, err
+ 
+       if rs:
+         if not self._fieldNames:
+           self._fieldNames = []
+           for t in (self._cursor.description):
+             self._fieldNames.append (string.lower(t[0]))
+             self._fieldTypes[string.lower(t[0])] = (string.lower(t[1]))
+         i = 0
+         dict = {}
+         for f in (rs):
+           dict[self._fieldNames[i]] = f
+           i = i + 1
+         self._cachedRecords.append (self._recordSetClass(parent=self, \
+                                             initialData=dict))
+         return 1
+       else:
+         return 0
+     else:
+       return 0
+ 
+ 
+ class ODBC_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     ),
+        '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     ) }
+ 
+   def __init__(self, strictQueryCount=1):
+     GDataObjects.DataObject.__init__(self)
+ 
+     GDebug.printMesg (1,"DB-SIG database driver backend initializing")
+ 
+     self._resultSetClass = ODBC_ResultSet
+     self._DatabaseError = None
+     self._strictQueryCount = strictQueryCount
+ 
+ 
+   # This should be over-ridden only if driver needs more than user/pass
+   def getLoginFields(self):
+     return [['_username', 'User Name',0],['_password', 'Password',1]]
+ 
+ 
+   def connect(self, connectData={}):
+ 
+     GDebug.printMesg(1,"ODBC database driver initializing")
+     self._DatabaseError = odbc.error
+ 
+     try:
+       service = connectData['service']
+     except KeyError:
+       service = ""
+ 
+     try:
+       self._dataConnection = odbc.odbc( "%s/%s/%s" % (
+                    service,
+                    connectData['_username'],
+                    connectData['_password']))
+ 
+     except dbi.opError, value:
+       raise GDataObjects.LoginError, value
+ 
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return None # [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+   def _createResultSet(self, conditions={}, readOnly=0, 
masterRecordSet=None,sql=""):
+     try:
+       cursor = self._dataConnection.cursor()
+       cursor.execute(self._buildQuery(conditions))
+ 
+     except dbi.progError, err:
+       raise GDataObjects.ConnectionError, err
+ 
+     except self._DatabaseError, err:
+       raise GDataObjects.ConnectionError, err
+     rs = self._resultSetClass(self, cursor=cursor, 
masterRecordSet=masterRecordSet)
+ 
+     # pull a record count for the upcomming query
+     if self._strictQueryCount:
+       rs._recordCount = self._getQueryCount(conditions)
+ 
+     if readOnly:
+       rs._readonly = readOnly
+     return rs
+ 
+ 
+   def _getQueryCount(self,conditions={}):
+     cursor = self._dataConnection.cursor()
+ 
+     cursor.execute(self._buildQueryCount(conditions))
+     rs = cursor.fetchone()
+     return int(rs[0])
+ 
+     
+   def _buildQueryCount(self, conditions={}):
+     q = "SELECT count(*) FROM %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+   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()
+ 
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return None
+ 
+ 
+   # 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
+   def __conditionToSQL (self, element): 
+     if type(element) != types.InstanceType: 
+       return "%s" % element
+     else: 
+       otype = string.lower(element._type[2:])
+       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 "'%s'" % element.value
+       elif otype == 'param':
+         v = element.getValue()
+         return (v == None and "NULL") or ("'%s'" % element.getValue())
+       elif self.conditionElements.has_key(otype):
+         for i in range(0, len(element._children)): 
+           element._children[i] = self.__conditionToSQL(element._children[i])
+         if len(element._children) < self.conditionElements[otype][0]: 
+           tmsg = _('Condition element "%s" expects at least %s arguments; 
found %s') % \
+                 (otype, self.conditionElements[otype][0], 
len(element._children))
+           raise GConditions.ConditionError, tmsg
+         if len(element._children) > self.conditionElements[otype][1]: 
+           tmsg = _('Condition element "%s" expects at most %s arguments; 
found %s') % \
+                 (otype, self.conditionElements[otype][0], 
len(element._children))
+           raise GConditions.ConditionError, tmsg
+         if self.conditionElements[otype][3] == None: 
+           return self.conditionElements[otype][2] % tuple(element._children)
+         else: 
+           return self.conditionElements[otype][2] % \
+             (string.join(element._children, 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      
+ 
+ 
+ class ODBC_DataObject_Object(ODBC_DataObject): 
+   def _buildQuery(self, conditions={}): 
+     GDebug.printMesg(7,'Implicit Fields: %s' % self._fieldReferences)
+     if len(self._fieldReferences):
+       q = "SELECT %s FROM %s%s" % \
+            (string.join(self._fieldReferences.keys(),","), self.table, 
+             self._conditionToSQL(conditions))
+     else: 
+       q = "SELECT * FROM %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     if hasattr(self,'order_by'):
+      q = "%s ORDER BY %s " % (q, self.order_by)
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': ODBC_DataObject_Object,
+ #  'sql':    ODBC_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/odbc/wodbc/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/odbc/wodbc/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:54 2003
--- gnue-common/src/datasources/drivers/odbc/wodbc/RecordSet.py Thu Oct  9 
21:21:22 2003
***************
*** 0 ****
--- 1,476 ----
+ #
+ # 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:
+ # odbc/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via the public domain win32all ODBC Driver
+ #
+ # NOTES:
+ # Only works under Win32... requires the win32all extensions.
+ # 
(http://aspn.activestate.com/ASPN/Downloads/ActivePython/Extensions/Win32all)
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=   This is the ODBC DSN= string to use.
+ #
+ #
+ 
+ 
+ import sys, string, types
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ 
+ 
+ try:
+   import dbi, odbc
+ except ImportError, message:
+   tmsg = _("Driver not installed: win32all ODBC driver\n\n[%s") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ 
+ 
+ class ODBC_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 = {}
+         for key in self._fields.keys():
+           self._initialData[key] = self._fields[key]
+ 
+     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._primaryIdField):
+       where = [self._parent._primaryIdFormat % \
+           self._initialData[self._parent._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._initialData[field]))
+ 
+     statement = "DELETE FROM %s WHERE %s" % \
+        (self._parent._dataObject.table, string.join(where,' AND ') )
+     return statement
+ 
+   def _buildInsertStatement(self): 
+     vals = []
+     fields = []
+ 
+     # TODO: This should actually only insert modified fields.
+     # TODO: Unfortunately, self._modifiedFlags is not being 
+     # TODO: set for new records (address@hidden)
+     #for field in self._modifiedFlags.keys():
+ 
+     for field in self._fields.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:
+           try: 
+             if self._parent._fieldTypes[field] == 'number': 
+               vals.append ("%s" % (self._fields[field]))
+             else: 
+               vals.append ("'%s'" % (self._fields[field]))
+           except ValueError:
+             vals.append ("%s" % (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():
+       try:
+         if self._parent._fieldTypes[field] == 'number':
+           updates.append ("%s=%s" % (field, self._fields[field]))
+         else:
+           updates.append ("%s='%s'" % (field, self._fields[field]))
+       except KeyError:
+         updates.append ("%s='%s'" % (field, self._fields[field]))
+ 
+     if self._initialData.has_key(self._parent._primaryIdField):
+       where = [self._parent._primaryIdFormat % \
+           self._initialData[self._parent._primaryIdField]  ]
+     else:
+       where = []
+       for field in self._initialData.keys():
+         if self._initialData[field] == None:
+           where.append ("%s IS NULL" % field)
+         else:
+           try:
+             if self._parent._fieldTypes[field] == 'number':
+               where.append ("%s=%s" % (field, self._initialData[field]))
+             else:
+               where.append ("%s='%s'" % (field, self._initialData[field]))
+           except KeyError:
+             where.append ("%s='%s'" % (field, self._initialData[field]))
+ 
+     return "UPDATE %s SET %s WHERE %s" % \
+        (self._parent._dataObject.table, string.join(updates,','), \
+         string.join(where,' AND ') )
+ 
+ 
+ class ODBC_ResultSet(GDataObjects.ResultSet): 
+   def __init__(self, dataObject, cursor=None, \
+         defaultValues={}, masterRecordSet=None):
+     GDataObjects.ResultSet.__init__(
+            self,dataObject,cursor,defaultValues,masterRecordSet)
+     self._recordSetClass = ODBC_RecordSet
+     self._fieldNames = None
+     self._fieldTypes = {}
+ 
+ #    self._recordCount = cursor.rowcount > 0 and cursor.rowcount or 0
+     self._recordCount = 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.
+     self._primaryIdField = None
+     self._primaryIdFormat = "__gnue__ = '%s'"
+ 
+     GDebug.printMesg(5, 'ResultSet created')
+ 
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         rs = self._cursor.fetchone()
+       except self._dataObject._DatabaseError, err:
+         pass
+ # TODO: It seems that popy does what the other drivers don't
+ # TODO: and raises this error ALOT need to find out why
+ #        raise GDataObjects.ConnectionError, err
+ 
+       if rs:
+         if not self._fieldNames:
+           self._fieldNames = []
+           for t in (self._cursor.description):
+             self._fieldNames.append (string.lower(t[0]))
+             self._fieldTypes[string.lower(t[0])] = (string.lower(t[1]))
+         i = 0
+         dict = {}
+         for f in (rs):
+           dict[self._fieldNames[i]] = f
+           i = i + 1
+         self._cachedRecords.append (self._recordSetClass(parent=self, \
+                                             initialData=dict))
+         return 1
+       else:
+         return 0
+     else:
+       return 0
+ 
+ 
+ class ODBC_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     ),
+        '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     ) }
+ 
+   def __init__(self, strictQueryCount=1):
+     GDataObjects.DataObject.__init__(self)
+ 
+     GDebug.printMesg (1,"DB-SIG database driver backend initializing")
+ 
+     self._resultSetClass = ODBC_ResultSet
+     self._DatabaseError = None
+     self._strictQueryCount = strictQueryCount
+ 
+ 
+   # This should be over-ridden only if driver needs more than user/pass
+   def getLoginFields(self):
+     return [['_username', 'User Name',0],['_password', 'Password',1]]
+ 
+ 
+   def connect(self, connectData={}):
+ 
+     GDebug.printMesg(1,"ODBC database driver initializing")
+     self._DatabaseError = odbc.error
+ 
+     try:
+       service = connectData['service']
+     except KeyError:
+       service = ""
+ 
+     try:
+       self._dataConnection = odbc.odbc( "%s/%s/%s" % (
+                    service,
+                    connectData['_username'],
+                    connectData['_password']))
+ 
+     except dbi.opError, value:
+       raise GDataObjects.LoginError, value
+ 
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return None # [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+   def _createResultSet(self, conditions={}, readOnly=0, 
masterRecordSet=None,sql=""):
+     try:
+       cursor = self._dataConnection.cursor()
+       cursor.execute(self._buildQuery(conditions))
+ 
+     except dbi.progError, err:
+       raise GDataObjects.ConnectionError, err
+ 
+     except self._DatabaseError, err:
+       raise GDataObjects.ConnectionError, err
+     rs = self._resultSetClass(self, cursor=cursor, 
masterRecordSet=masterRecordSet)
+ 
+     # pull a record count for the upcomming query
+     if self._strictQueryCount:
+       rs._recordCount = self._getQueryCount(conditions)
+ 
+     if readOnly:
+       rs._readonly = readOnly
+     return rs
+ 
+ 
+   def _getQueryCount(self,conditions={}):
+     cursor = self._dataConnection.cursor()
+ 
+     cursor.execute(self._buildQueryCount(conditions))
+     rs = cursor.fetchone()
+     return int(rs[0])
+ 
+     
+   def _buildQueryCount(self, conditions={}):
+     q = "SELECT count(*) FROM %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+   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()
+ 
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return None
+ 
+ 
+   # 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
+   def __conditionToSQL (self, element): 
+     if type(element) != types.InstanceType: 
+       return "%s" % element
+     else: 
+       otype = string.lower(element._type[2:])
+       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 "'%s'" % element.value
+       elif otype == 'param':
+         v = element.getValue()
+         return (v == None and "NULL") or ("'%s'" % element.getValue())
+       elif self.conditionElements.has_key(otype):
+         for i in range(0, len(element._children)): 
+           element._children[i] = self.__conditionToSQL(element._children[i])
+         if len(element._children) < self.conditionElements[otype][0]: 
+           tmsg = _('Condition element "%s" expects at least %s arguments; 
found %s') % \
+                 (otype, self.conditionElements[otype][0], 
len(element._children))
+           raise GConditions.ConditionError, tmsg
+         if len(element._children) > self.conditionElements[otype][1]: 
+           tmsg = _('Condition element "%s" expects at most %s arguments; 
found %s') % \
+                 (otype, self.conditionElements[otype][0], 
len(element._children))
+           raise GConditions.ConditionError, tmsg
+         if self.conditionElements[otype][3] == None: 
+           return self.conditionElements[otype][2] % tuple(element._children)
+         else: 
+           return self.conditionElements[otype][2] % \
+             (string.join(element._children, 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      
+ 
+ 
+ class ODBC_DataObject_Object(ODBC_DataObject): 
+   def _buildQuery(self, conditions={}): 
+     GDebug.printMesg(7,'Implicit Fields: %s' % self._fieldReferences)
+     if len(self._fieldReferences):
+       q = "SELECT %s FROM %s%s" % \
+            (string.join(self._fieldReferences.keys(),","), self.table, 
+             self._conditionToSQL(conditions))
+     else: 
+       q = "SELECT * FROM %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     if hasattr(self,'order_by'):
+      q = "%s ORDER BY %s " % (q, self.order_by)
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': ODBC_DataObject_Object,
+ #  'sql':    ODBC_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/odbc/wodbc/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/odbc/wodbc/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:54 2003
--- gnue-common/src/datasources/drivers/odbc/wodbc/ResultSet.py Thu Oct  9 
21:21:22 2003
***************
*** 0 ****
--- 1,476 ----
+ #
+ # 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:
+ # odbc/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via the public domain win32all ODBC Driver
+ #
+ # NOTES:
+ # Only works under Win32... requires the win32all extensions.
+ # 
(http://aspn.activestate.com/ASPN/Downloads/ActivePython/Extensions/Win32all)
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=   This is the ODBC DSN= string to use.
+ #
+ #
+ 
+ 
+ import sys, string, types
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ 
+ 
+ try:
+   import dbi, odbc
+ except ImportError, message:
+   tmsg = _("Driver not installed: win32all ODBC driver\n\n[%s") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ 
+ 
+ class ODBC_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 = {}
+         for key in self._fields.keys():
+           self._initialData[key] = self._fields[key]
+ 
+     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._primaryIdField):
+       where = [self._parent._primaryIdFormat % \
+           self._initialData[self._parent._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._initialData[field]))
+ 
+     statement = "DELETE FROM %s WHERE %s" % \
+        (self._parent._dataObject.table, string.join(where,' AND ') )
+     return statement
+ 
+   def _buildInsertStatement(self): 
+     vals = []
+     fields = []
+ 
+     # TODO: This should actually only insert modified fields.
+     # TODO: Unfortunately, self._modifiedFlags is not being 
+     # TODO: set for new records (address@hidden)
+     #for field in self._modifiedFlags.keys():
+ 
+     for field in self._fields.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:
+           try: 
+             if self._parent._fieldTypes[field] == 'number': 
+               vals.append ("%s" % (self._fields[field]))
+             else: 
+               vals.append ("'%s'" % (self._fields[field]))
+           except ValueError:
+             vals.append ("%s" % (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():
+       try:
+         if self._parent._fieldTypes[field] == 'number':
+           updates.append ("%s=%s" % (field, self._fields[field]))
+         else:
+           updates.append ("%s='%s'" % (field, self._fields[field]))
+       except KeyError:
+         updates.append ("%s='%s'" % (field, self._fields[field]))
+ 
+     if self._initialData.has_key(self._parent._primaryIdField):
+       where = [self._parent._primaryIdFormat % \
+           self._initialData[self._parent._primaryIdField]  ]
+     else:
+       where = []
+       for field in self._initialData.keys():
+         if self._initialData[field] == None:
+           where.append ("%s IS NULL" % field)
+         else:
+           try:
+             if self._parent._fieldTypes[field] == 'number':
+               where.append ("%s=%s" % (field, self._initialData[field]))
+             else:
+               where.append ("%s='%s'" % (field, self._initialData[field]))
+           except KeyError:
+             where.append ("%s='%s'" % (field, self._initialData[field]))
+ 
+     return "UPDATE %s SET %s WHERE %s" % \
+        (self._parent._dataObject.table, string.join(updates,','), \
+         string.join(where,' AND ') )
+ 
+ 
+ class ODBC_ResultSet(GDataObjects.ResultSet): 
+   def __init__(self, dataObject, cursor=None, \
+         defaultValues={}, masterRecordSet=None):
+     GDataObjects.ResultSet.__init__(
+            self,dataObject,cursor,defaultValues,masterRecordSet)
+     self._recordSetClass = ODBC_RecordSet
+     self._fieldNames = None
+     self._fieldTypes = {}
+ 
+ #    self._recordCount = cursor.rowcount > 0 and cursor.rowcount or 0
+     self._recordCount = 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.
+     self._primaryIdField = None
+     self._primaryIdFormat = "__gnue__ = '%s'"
+ 
+     GDebug.printMesg(5, 'ResultSet created')
+ 
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         rs = self._cursor.fetchone()
+       except self._dataObject._DatabaseError, err:
+         pass
+ # TODO: It seems that popy does what the other drivers don't
+ # TODO: and raises this error ALOT need to find out why
+ #        raise GDataObjects.ConnectionError, err
+ 
+       if rs:
+         if not self._fieldNames:
+           self._fieldNames = []
+           for t in (self._cursor.description):
+             self._fieldNames.append (string.lower(t[0]))
+             self._fieldTypes[string.lower(t[0])] = (string.lower(t[1]))
+         i = 0
+         dict = {}
+         for f in (rs):
+           dict[self._fieldNames[i]] = f
+           i = i + 1
+         self._cachedRecords.append (self._recordSetClass(parent=self, \
+                                             initialData=dict))
+         return 1
+       else:
+         return 0
+     else:
+       return 0
+ 
+ 
+ class ODBC_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     ),
+        '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     ) }
+ 
+   def __init__(self, strictQueryCount=1):
+     GDataObjects.DataObject.__init__(self)
+ 
+     GDebug.printMesg (1,"DB-SIG database driver backend initializing")
+ 
+     self._resultSetClass = ODBC_ResultSet
+     self._DatabaseError = None
+     self._strictQueryCount = strictQueryCount
+ 
+ 
+   # This should be over-ridden only if driver needs more than user/pass
+   def getLoginFields(self):
+     return [['_username', 'User Name',0],['_password', 'Password',1]]
+ 
+ 
+   def connect(self, connectData={}):
+ 
+     GDebug.printMesg(1,"ODBC database driver initializing")
+     self._DatabaseError = odbc.error
+ 
+     try:
+       service = connectData['service']
+     except KeyError:
+       service = ""
+ 
+     try:
+       self._dataConnection = odbc.odbc( "%s/%s/%s" % (
+                    service,
+                    connectData['_username'],
+                    connectData['_password']))
+ 
+     except dbi.opError, value:
+       raise GDataObjects.LoginError, value
+ 
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return None # [('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+   def _createResultSet(self, conditions={}, readOnly=0, 
masterRecordSet=None,sql=""):
+     try:
+       cursor = self._dataConnection.cursor()
+       cursor.execute(self._buildQuery(conditions))
+ 
+     except dbi.progError, err:
+       raise GDataObjects.ConnectionError, err
+ 
+     except self._DatabaseError, err:
+       raise GDataObjects.ConnectionError, err
+     rs = self._resultSetClass(self, cursor=cursor, 
masterRecordSet=masterRecordSet)
+ 
+     # pull a record count for the upcomming query
+     if self._strictQueryCount:
+       rs._recordCount = self._getQueryCount(conditions)
+ 
+     if readOnly:
+       rs._readonly = readOnly
+     return rs
+ 
+ 
+   def _getQueryCount(self,conditions={}):
+     cursor = self._dataConnection.cursor()
+ 
+     cursor.execute(self._buildQueryCount(conditions))
+     rs = cursor.fetchone()
+     return int(rs[0])
+ 
+     
+   def _buildQueryCount(self, conditions={}):
+     q = "SELECT count(*) FROM %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+   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()
+ 
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return None
+ 
+ 
+   # 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
+   def __conditionToSQL (self, element): 
+     if type(element) != types.InstanceType: 
+       return "%s" % element
+     else: 
+       otype = string.lower(element._type[2:])
+       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 "'%s'" % element.value
+       elif otype == 'param':
+         v = element.getValue()
+         return (v == None and "NULL") or ("'%s'" % element.getValue())
+       elif self.conditionElements.has_key(otype):
+         for i in range(0, len(element._children)): 
+           element._children[i] = self.__conditionToSQL(element._children[i])
+         if len(element._children) < self.conditionElements[otype][0]: 
+           tmsg = _('Condition element "%s" expects at least %s arguments; 
found %s') % \
+                 (otype, self.conditionElements[otype][0], 
len(element._children))
+           raise GConditions.ConditionError, tmsg
+         if len(element._children) > self.conditionElements[otype][1]: 
+           tmsg = _('Condition element "%s" expects at most %s arguments; 
found %s') % \
+                 (otype, self.conditionElements[otype][0], 
len(element._children))
+           raise GConditions.ConditionError, tmsg
+         if self.conditionElements[otype][3] == None: 
+           return self.conditionElements[otype][2] % tuple(element._children)
+         else: 
+           return self.conditionElements[otype][2] % \
+             (string.join(element._children, 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      
+ 
+ 
+ class ODBC_DataObject_Object(ODBC_DataObject): 
+   def _buildQuery(self, conditions={}): 
+     GDebug.printMesg(7,'Implicit Fields: %s' % self._fieldReferences)
+     if len(self._fieldReferences):
+       q = "SELECT %s FROM %s%s" % \
+            (string.join(self._fieldReferences.keys(),","), self.table, 
+             self._conditionToSQL(conditions))
+     else: 
+       q = "SELECT * FROM %s%s" % (self.table, 
self._conditionToSQL(conditions))
+ 
+     if hasattr(self,'order_by'):
+      q = "%s ORDER BY %s " % (q, self.order_by)
+ 
+     GDebug.printMesg(5,q)
+ 
+     return q
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': ODBC_DataObject_Object,
+ #  'sql':    ODBC_DataObject_SQL
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/odbc/wodbc/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/odbc/wodbc/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:55 2003
--- gnue-common/src/datasources/drivers/odbc/wodbc/__init__.py  Thu Oct  9 
21:21:22 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("Windows ODBC Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/oracle/Base/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/Base/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:55 2003
--- gnue-common/src/datasources/drivers/oracle/Base/Connection.py       Thu Oct 
 9 21:21:23 2003
***************
*** 0 ****
--- 1,99 ----
+ #
+ # 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:
+ # cxoracle/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Computronix's Oracle/Python Driver
+ # Requires cx_Oracle 2.2+ (http://www.computronix.com/utilities/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Oracle TNS name for your connection  (required)
+ #
+ 
+ __all__ = ['Connection']
+ 
+ import sys, string
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ from gnue.common.datasources.drivers.oracle.Schema.Discovery.Introspection 
import Introspection
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class Connection(DBSIG2.Connection):
+ 
+   _defaultBehavior = Introspection
+ 
+   
+   #
+   #  Extensions
+   #
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select sysdate from dual")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select %s.nextval from dual" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+     try:
+       return cursor.fetchall()
+     except: 
+       return None
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except mesg:
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % mesg)
+       cursor.close()
+       return None
+ 
+     try:
+       return rv[0]
+     except:
+       return None
+ 
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/oracle/Base/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/Base/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:55 2003
--- gnue-common/src/datasources/drivers/oracle/Base/DataObject.py       Thu Oct 
 9 21:21:23 2003
***************
*** 0 ****
--- 1,237 ----
+ #
+ # 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:
+ # cxoracle/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Computronix's Oracle/Python Driver
+ # Requires cx_Oracle 2.2+ (http://www.computronix.com/utilities/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Oracle TNS name for your connection  (required)
+ #
+ 
+ import sys, string
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ 
+ class Oracle_Schema:
+ 
+   def __init__(self):
+     pass
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [ ('user_table',   _('User Tables'),1),
+              ('user_view',    _('User Views'),1),
+              ('user_synonym', _('User Synonyms'),1),
+              ('all_table',    _('System Tables'),1),
+              ('all_view',     _('System Views'),1),
+              ('all_synonym',  _('System Synonyms'),1) ]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = ['TABLE', 'VIEW', 'SYNONYM']
+     else:
+       scope, type = string.split(type,'_')
+       where_type = [string.upper(type)]
+       if scope == 'user':
+         where_user = " AND OWNER = USER"
+ 
+ 
+     statement = \
+       "select owner||'.'||table_name||'.'||table_type full_name, \n" + \
+       "  decode(owner,user,null,owner||'.')||table_name table_name, \n" + \
+       "  decode(owner,user,'user_','all_')||lower(table_type) table_type \n" 
+ \
+       "  from all_catalog where table_type in ('%s') %s \n" \
+               % (string.join(where_type,"','"), where_user) + \
+       "  order by table_name "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 
'name':string.lower(rs[1]),
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     spl = string.split(string.upper(name),'.')
+     where = "TABLE_NAME='%s'" % spl[-1]
+     if len(spl) > 1:
+       where += " AND OWNER='%s'" % spl[-2]
+ 
+     statement = \
+       "select owner||'.'||table_name||'.'||table_type full_name, \n" + \
+       "  decode(owner,user,null,owner||'.')||table_name table_name, \n" + \
+       "  decode(owner,user,'user_','all_')||lower(table_type) table_type \n" 
+ \
+       "  from all_catalog where %s " \
+               % (where)
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     rs = cursor.fetchone()
+     if rs:
+       rv = GDataObjects.Schema(attrs={'id':rs[0], 'name':string.lower(rs[1]),
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema)
+     else:
+       rv = None
+ 
+     cursor.close()
+     return rv
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     owner, name, type = string.split(parent.id,'.')
+ 
+     cursor = self._dataConnection.cursor()
+ 
+     if type == 'SYNONYM':
+       statement = "select table_owner, table_name, " + \
+                   "decode(db_link,null,'','@'||db_link) name " + \
+                   "from all_synonyms " + \
+                   "where owner = '%s' and synonym_name='%s'" % (owner, name)
+ 
+       GDebug.printMesg(5,statement)
+ 
+       cursor.execute(statement)
+       rs = cursor.fetchone()
+       owner, name, link = rs
+       if link is None:
+         link = ""
+     else:
+       link = ""
+ 
+     statement = \
+        "select owner||'.'||table_name||'.'||column_name||'.%s', " % (link) + \
+        "column_name, data_type, nullable, data_length, data_scale, 
data_precision " + \
+        "from all_tab_columns%s " % (link) + \
+        "where owner = '%s' and table_name = '%s' " % (owner, name) + \
+        "order by column_id"
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': string.lower(rs[1]),
+              'type':'field', 'nativetype': rs[2],
+              'required': rs[3] == 'N'}
+ 
+       if rs[2] in ('NUMBER',):
+         attrs['precision'] = int(rs[5])
+         attrs['datatype'] = 'number'
+         attrs['length'] = int(rs[6])
+       elif rs[2] in ('DATE',):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+         if int(rs[4]):
+           attrs['length'] = int(rs[4])
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select sysdate from dual")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select %s.nextval from dual" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+     try: 
+       return cursor.fetchall()
+     except: 
+       return None
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except mesg:
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % mesg)
+       cursor.close()
+       return None
+ 
+     try:
+       return rv[0]
+     except:
+       return None
+ 
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/oracle/Base/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/Base/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:55 2003
--- gnue-common/src/datasources/drivers/oracle/Base/RecordSet.py        Thu Oct 
 9 21:21:23 2003
***************
*** 0 ****
--- 1,237 ----
+ #
+ # 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:
+ # cxoracle/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Computronix's Oracle/Python Driver
+ # Requires cx_Oracle 2.2+ (http://www.computronix.com/utilities/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Oracle TNS name for your connection  (required)
+ #
+ 
+ import sys, string
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ 
+ class Oracle_Schema:
+ 
+   def __init__(self):
+     pass
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [ ('user_table',   _('User Tables'),1),
+              ('user_view',    _('User Views'),1),
+              ('user_synonym', _('User Synonyms'),1),
+              ('all_table',    _('System Tables'),1),
+              ('all_view',     _('System Views'),1),
+              ('all_synonym',  _('System Synonyms'),1) ]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = ['TABLE', 'VIEW', 'SYNONYM']
+     else:
+       scope, type = string.split(type,'_')
+       where_type = [string.upper(type)]
+       if scope == 'user':
+         where_user = " AND OWNER = USER"
+ 
+ 
+     statement = \
+       "select owner||'.'||table_name||'.'||table_type full_name, \n" + \
+       "  decode(owner,user,null,owner||'.')||table_name table_name, \n" + \
+       "  decode(owner,user,'user_','all_')||lower(table_type) table_type \n" 
+ \
+       "  from all_catalog where table_type in ('%s') %s \n" \
+               % (string.join(where_type,"','"), where_user) + \
+       "  order by table_name "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 
'name':string.lower(rs[1]),
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     spl = string.split(string.upper(name),'.')
+     where = "TABLE_NAME='%s'" % spl[-1]
+     if len(spl) > 1:
+       where += " AND OWNER='%s'" % spl[-2]
+ 
+     statement = \
+       "select owner||'.'||table_name||'.'||table_type full_name, \n" + \
+       "  decode(owner,user,null,owner||'.')||table_name table_name, \n" + \
+       "  decode(owner,user,'user_','all_')||lower(table_type) table_type \n" 
+ \
+       "  from all_catalog where %s " \
+               % (where)
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     rs = cursor.fetchone()
+     if rs:
+       rv = GDataObjects.Schema(attrs={'id':rs[0], 'name':string.lower(rs[1]),
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema)
+     else:
+       rv = None
+ 
+     cursor.close()
+     return rv
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     owner, name, type = string.split(parent.id,'.')
+ 
+     cursor = self._dataConnection.cursor()
+ 
+     if type == 'SYNONYM':
+       statement = "select table_owner, table_name, " + \
+                   "decode(db_link,null,'','@'||db_link) name " + \
+                   "from all_synonyms " + \
+                   "where owner = '%s' and synonym_name='%s'" % (owner, name)
+ 
+       GDebug.printMesg(5,statement)
+ 
+       cursor.execute(statement)
+       rs = cursor.fetchone()
+       owner, name, link = rs
+       if link is None:
+         link = ""
+     else:
+       link = ""
+ 
+     statement = \
+        "select owner||'.'||table_name||'.'||column_name||'.%s', " % (link) + \
+        "column_name, data_type, nullable, data_length, data_scale, 
data_precision " + \
+        "from all_tab_columns%s " % (link) + \
+        "where owner = '%s' and table_name = '%s' " % (owner, name) + \
+        "order by column_id"
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': string.lower(rs[1]),
+              'type':'field', 'nativetype': rs[2],
+              'required': rs[3] == 'N'}
+ 
+       if rs[2] in ('NUMBER',):
+         attrs['precision'] = int(rs[5])
+         attrs['datatype'] = 'number'
+         attrs['length'] = int(rs[6])
+       elif rs[2] in ('DATE',):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+         if int(rs[4]):
+           attrs['length'] = int(rs[4])
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select sysdate from dual")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select %s.nextval from dual" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+     try: 
+       return cursor.fetchall()
+     except: 
+       return None
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except mesg:
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % mesg)
+       cursor.close()
+       return None
+ 
+     try:
+       return rv[0]
+     except:
+       return None
+ 
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/oracle/Base/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/Base/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:55 2003
--- gnue-common/src/datasources/drivers/oracle/Base/ResultSet.py        Thu Oct 
 9 21:21:23 2003
***************
*** 0 ****
--- 1,237 ----
+ #
+ # 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:
+ # cxoracle/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Computronix's Oracle/Python Driver
+ # Requires cx_Oracle 2.2+ (http://www.computronix.com/utilities/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Oracle TNS name for your connection  (required)
+ #
+ 
+ import sys, string
+ from gnue.common.datasources import GDataObjects, GConditions
+ from gnue.common.apps import GDebug
+ 
+ class Oracle_Schema:
+ 
+   def __init__(self):
+     pass
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [ ('user_table',   _('User Tables'),1),
+              ('user_view',    _('User Views'),1),
+              ('user_synonym', _('User Synonyms'),1),
+              ('all_table',    _('System Tables'),1),
+              ('all_view',     _('System Views'),1),
+              ('all_synonym',  _('System Synonyms'),1) ]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = ['TABLE', 'VIEW', 'SYNONYM']
+     else:
+       scope, type = string.split(type,'_')
+       where_type = [string.upper(type)]
+       if scope == 'user':
+         where_user = " AND OWNER = USER"
+ 
+ 
+     statement = \
+       "select owner||'.'||table_name||'.'||table_type full_name, \n" + \
+       "  decode(owner,user,null,owner||'.')||table_name table_name, \n" + \
+       "  decode(owner,user,'user_','all_')||lower(table_type) table_type \n" 
+ \
+       "  from all_catalog where table_type in ('%s') %s \n" \
+               % (string.join(where_type,"','"), where_user) + \
+       "  order by table_name "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 
'name':string.lower(rs[1]),
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     spl = string.split(string.upper(name),'.')
+     where = "TABLE_NAME='%s'" % spl[-1]
+     if len(spl) > 1:
+       where += " AND OWNER='%s'" % spl[-2]
+ 
+     statement = \
+       "select owner||'.'||table_name||'.'||table_type full_name, \n" + \
+       "  decode(owner,user,null,owner||'.')||table_name table_name, \n" + \
+       "  decode(owner,user,'user_','all_')||lower(table_type) table_type \n" 
+ \
+       "  from all_catalog where %s " \
+               % (where)
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     rs = cursor.fetchone()
+     if rs:
+       rv = GDataObjects.Schema(attrs={'id':rs[0], 'name':string.lower(rs[1]),
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema)
+     else:
+       rv = None
+ 
+     cursor.close()
+     return rv
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     owner, name, type = string.split(parent.id,'.')
+ 
+     cursor = self._dataConnection.cursor()
+ 
+     if type == 'SYNONYM':
+       statement = "select table_owner, table_name, " + \
+                   "decode(db_link,null,'','@'||db_link) name " + \
+                   "from all_synonyms " + \
+                   "where owner = '%s' and synonym_name='%s'" % (owner, name)
+ 
+       GDebug.printMesg(5,statement)
+ 
+       cursor.execute(statement)
+       rs = cursor.fetchone()
+       owner, name, link = rs
+       if link is None:
+         link = ""
+     else:
+       link = ""
+ 
+     statement = \
+        "select owner||'.'||table_name||'.'||column_name||'.%s', " % (link) + \
+        "column_name, data_type, nullable, data_length, data_scale, 
data_precision " + \
+        "from all_tab_columns%s " % (link) + \
+        "where owner = '%s' and table_name = '%s' " % (owner, name) + \
+        "order by column_id"
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': string.lower(rs[1]),
+              'type':'field', 'nativetype': rs[2],
+              'required': rs[3] == 'N'}
+ 
+       if rs[2] in ('NUMBER',):
+         attrs['precision'] = int(rs[5])
+         attrs['datatype'] = 'number'
+         attrs['length'] = int(rs[6])
+       elif rs[2] in ('DATE',):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+         if int(rs[4]):
+           attrs['length'] = int(rs[4])
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select sysdate from dual")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select %s.nextval from dual" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+     try: 
+       return cursor.fetchall()
+     except: 
+       return None
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.__connection.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except mesg:
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % mesg)
+       cursor.close()
+       return None
+ 
+     try:
+       return rv[0]
+     except:
+       return None
+ 
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/oracle/Base/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/Base/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:56 2003
--- gnue-common/src/datasources/drivers/oracle/Base/__init__.py Thu Oct  9 
21:21:23 2003
***************
*** 0 ****
--- 1,25 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ from DataObject import *
+ from ResultSet import *
+ from RecordSet import *
Index: 
gnue-common/src/datasources/drivers/oracle/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:56 2003
--- 
gnue-common/src/datasources/drivers/oracle/Schema/Discovery/Introspection.py    
    Thu Oct  9 21:21:24 2003
***************
*** 0 ****
--- 1,192 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =  [ ('user_table',   _('User Tables'),1),
+              ('user_view',    _('User Views'),1),
+              ('user_synonym', _('User Synonyms'),1),
+              ('all_table',    _('System Tables'),1),
+              ('all_view',     _('System Views'),1),
+              ('all_synonym',  _('System Synonyms'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = ['TABLE', 'VIEW', 'SYNONYM']
+     else:
+       scope, type = string.split(type,'_')
+       where_type = [string.upper(type)]
+       if scope == 'user':
+         where_user = " AND OWNER = USER"
+ 
+ 
+     statement = \
+       "select owner||'.'||table_name||'.'||table_type full_name, \n" + \
+       "  decode(owner,user,null,owner||'.')||table_name table_name, \n" + \
+       "  decode(owner,user,'user_','all_')||lower(table_type) table_type \n" 
+ \
+       "  from all_catalog where table_type in ('%s') %s \n" \
+               % (string.join(where_type,"','"), where_user) + \
+       "  order by table_name "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 
'name':string.lower(rs[1]),
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     spl = string.split(string.upper(name),'.')
+     where = "TABLE_NAME='%s'" % spl[-1]
+     if len(spl) > 1:
+       where += " AND OWNER='%s'" % spl[-2]
+ 
+     statement = \
+       "select owner||'.'||table_name||'.'||table_type full_name, \n" + \
+       "  decode(owner,user,null,owner||'.')||table_name table_name, \n" + \
+       "  decode(owner,user,'user_','all_')||lower(table_type) table_type \n" 
+ \
+       "  from all_catalog where %s " \
+               % (where)
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     rs = cursor.fetchone()
+     if rs:
+       rv = GDataObjects.Schema(attrs={'id':rs[0], 'name':string.lower(rs[1]),
+                          'type':rs[2]},
+                          getChildSchema=self.__getFieldSchema)
+     else:
+       rv = None
+ 
+     cursor.close()
+     return rv
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     owner, name, type = string.split(parent.id,'.')
+ 
+     cursor = self.native.cursor()
+ 
+     if type == 'SYNONYM':
+       statement = "select table_owner, table_name, " + \
+                   "decode(db_link,null,'','@'||db_link) name " + \
+                   "from all_synonyms " + \
+                   "where owner = '%s' and synonym_name='%s'" % (owner, name)
+ 
+       GDebug.printMesg(5,statement)
+ 
+       cursor.execute(statement)
+       rs = cursor.fetchone()
+       owner, name, link = rs
+       if link is None:
+         link = ""
+     else:
+       link = ""
+ 
+     statement = \
+        "select owner||'.'||table_name||'.'||column_name||'.%s', " % (link) + \
+        "column_name, data_type, nullable, data_length, data_scale, 
data_precision " + \
+        "from all_tab_columns%s " % (link) + \
+        "where owner = '%s' and table_name = '%s' " % (owner, name) + \
+        "order by column_id"
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': string.lower(rs[1]),
+              'type':'field', 'nativetype': rs[2],
+              'required': rs[3] == 'N'}
+ 
+       if rs[2] in ('NUMBER',):
+         attrs['precision'] = int(rs[5])
+         attrs['datatype'] = 'number'
+         attrs['length'] = int(rs[6])
+       elif rs[2] in ('DATE',):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+         if int(rs[4]):
+           attrs['length'] = int(rs[4])
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
Index: gnue-common/src/datasources/drivers/oracle/cxoracle/Driver.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/cxoracle/Driver.py:1.20.2.1
*** /dev/null   Thu Oct  9 21:21:56 2003
--- gnue-common/src/datasources/drivers/oracle/cxoracle/Driver.py       Thu Oct 
 9 21:21:24 2003
***************
*** 0 ****
--- 1,145 ----
+ #
+ # 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:
+ # cxoracle/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Computronix's Oracle/Python Driver
+ # Requires cx_Oracle 2.2+ (http://www.computronix.com/utilities/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Oracle TNS name for your connection  (required)
+ #
+ 
+ import sys, string
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GDataObjects, GConnections
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ from gnue.common.datasources.drivers.oracle.Base.Driver import Oracle_Schema
+ 
+ try:
+   import cx_Oracle as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: cx_Oracle for Oracle 8.x [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Oracle_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Oracle_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Oracle_RecordSet
+ 
+ 
+ class Oracle_DataObject(Oracle_Schema, DBSIG2.DataObject):
+   def __init__(self):
+     Oracle_Schema.__init__(self)
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Oracle_ResultSet
+ 
+     # The date/time format used in insert/select statements
+     # (based on format used for time.strftime())
+     self._dateTimeFormat = "to_date('%Y-%m-%d %H:%M:%S','yyyy-mm-dd 
hh:mi:ss')"
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Oracle database driver initializing")
+     try:
+       self._dataConnection = SIG2api.connect("%s/address@hidden" \
+                 % (connectData['_username'], \
+                    connectData['_password'], \
+                    connectData['service']))
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ class Oracle_DataObject_Object(Oracle_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Oracle_DataObject.__init__(self)
+     self._primaryIdChecked = 0
+ 
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+   def _checkForPrimaryId(self):
+ 
+     self._primaryIdChecked = 1
+ 
+     try:
+       statement =  "select rowidtochar(rowid) from %s where 1=2" % self.table
+       cursor = self._dataConnection.cursor()
+       cursor.execute(statement)
+       cursor.close()
+ 
+       self._primaryIdSelect = "ROWIDTOCHAR(ROWID) as GNUE__ROWID__"
+       self._primaryIdField = "gnue__rowid__"  # Keep this lowercase!!!
+       self._primaryIdFormat = "ROWID = CHARTOROWID('%s')"
+       GDebug.printMesg(5,'View %s is using ROWID identifier' % self.table)
+ 
+     except self._DatabaseError:
+       GDebug.printMesg (5, 'View %s has no internal ROWID' % self.table)
+ 
+ 
+ class Oracle_DataObject_SQL(Oracle_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Oracle_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Oracle_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Oracle_DataObject_Object,
+   'sql':    Oracle_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/oracle/cxoracle/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/cxoracle/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:56 2003
--- gnue-common/src/datasources/drivers/oracle/cxoracle/__init__.py     Thu Oct 
 9 21:21:24 2003
***************
*** 0 ****
--- 1,6 ----
+ from Driver import *
+ 
+ __description__ = _("CX_Oracle Data Driver for Oracle 7.3/8i/9i+ (OCI8)")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/oracle/dcoracle/Driver.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/dcoracle/Driver.py:1.24.2.1
*** /dev/null   Thu Oct  9 21:21:57 2003
--- gnue-common/src/datasources/drivers/oracle/dcoracle/Driver.py       Thu Oct 
 9 21:21:25 2003
***************
*** 0 ****
--- 1,151 ----
+ #
+ # 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:
+ # oracle/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Digital Creations Oracle/Python Driver
+ # Requires DCOracle2 2.x (http://www.zope.org/Products/DCOracle2/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Oracle TNS name for your connection  (required)
+ #
+ 
+ import string
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ from gnue.common.datasources.drivers.oracle.Base.Driver import Oracle_Schema
+ 
+ try:
+   import DCOracle2 as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: DCOracle2 [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ 
+ class Oracle_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Oracle_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Oracle_RecordSet
+     self._uniqueIdField = "__GNUeF__uniqueKey_%s" % (self._dataObject.table)
+     self._uniqueIdFormat = "ROWID='%s'"
+ 
+ 
+ 
+ class Oracle_DataObject(Oracle_Schema, DBSIG2.DataObject):
+   def __init__(self):
+     Oracle_Schema.__init__(self)
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Oracle_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Oracle database driver initializing")
+     try:
+       self._dataConnection = SIG2api.connect("%s/address@hidden" \
+                 % (connectData['_username'], \
+                    connectData['_password'], \
+                    connectData['service']))
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     if connectData.has_key('datetimeformat'):
+       self._dateTimeFormat = "'%s'" % connectData['datetimeformat']
+ 
+     self._postConnect()
+ 
+ 
+ 
+ class Oracle_DataObject_Object(Oracle_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Oracle_DataObject.__init__(self)
+     self._primaryIdChecked = 0
+ 
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions, forDetail, 
additionalSQL)
+ 
+   def _checkForPrimaryId(self):
+ 
+     self._primaryIdChecked = 1
+ 
+     try:
+       statement =  "select rowidtochar(rowid) from %s where 1=2" % self.table
+       cursor = self._dataConnection.cursor()
+       cursor.execute(statement)
+       cursor.close()
+ 
+       self._primaryIdSelect = "ROWIDTOCHAR(ROWID) as GNUE__ROWID__"
+       self._primaryIdField = "gnue__rowid__"  # Keep this lowercase!!!
+       self._primaryIdFormat = "ROWID = CHARTOROWID('%s')"
+       GDebug.printMesg(5,'View %s is using ROWID identifier' % self.table)
+ 
+     except self._DatabaseError:
+       GDebug.printMesg (5, 'View %s has no internal ROWID' % self.table)
+ 
+ 
+ class Oracle_DataObject_SQL(Oracle_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Oracle_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Oracle_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Oracle_DataObject_Object,
+   'sql':    Oracle_DataObject_SQL
+ }
+ 
+ 
+ 
Index: gnue-common/src/datasources/drivers/oracle/dcoracle/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/oracle/dcoracle/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:57 2003
--- gnue-common/src/datasources/drivers/oracle/dcoracle/__init__.py     Thu Oct 
 9 21:21:26 2003
***************
*** 0 ****
--- 1,6 ----
+ from Driver import *
+ 
+ __description__ = _("DCOracle2 Data Driver for Oracle 7.3/8i/9i+ (OCI8)")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/postgresql/Base/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/Base/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:57 2003
--- gnue-common/src/datasources/drivers/postgresql/Base/Connection.py   Thu Oct 
 9 21:21:26 2003
***************
*** 0 ****
--- 1,154 ----
+ #
+ # 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:
+ # _pgsql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # A core Postgresql dbdriver that the other (specific)
+ # postgresql drivers can extend
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Connection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources.drivers import DBSIG2
+ from DataObject import *
+ from 
gnue.common.datasources.drivers.postgresql.Schema.Discovery.Introspection 
import Introspection
+ 
+ 
+ ######################################################################
+ #
+ #  GConnection object for PostgreSQL-based drivers
+ #
+ class Connection(DBSIG2.Connection):
+ 
+   _defaultBehavior = Introspection
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+   _pg_connectString = 'host=%s dbname=%s user=%s password=%s port=%s'
+   _pg_driver = None
+ 
+   def connect(self                                                            
                                                                                
                                                                                
              , connectData={}):
+ 
+     if not hasattr(self,'_DatabaseError'):
+       self._DatabaseError = self._pg_driver.DatabaseError
+ 
+     GDebug.printMesg(1,"Postgresql database driver initializing")
+     try:
+       try:
+         port = connectData['port']
+       except:
+         port  = '5432'
+ 
+       self.native = self._pg_driver.connect(self._pg_connectString %
+                                                     (connectData['host'],
+                                                      connectData['dbname'],
+                                                      connectData['_username'],
+                                                      connectData['_password'],
+                                                      port))
+     except self._DatabaseError, value:
+       GDebug.printMesg(1,"Connect String: %s" % (self._pg_connectString % \
+              (connectData['host'],
+               connectData['dbname'],
+               connectData['_username'],
+               connectData['_password'],
+               port)))
+       GDebug.printMesg(1,"Exception %s " % value)
+       raise GDataObjects.LoginError, value
+ 
+     try:
+       encoding = ""
+       try:
+         encoding = connectData['encoding']
+       except KeyError:
+         # if encoding is not defined in connectData use gnue.conf setting 
instead
+         try:
+           encoding = gConfig('encoding')
+         except:
+           pass
+ 
+       if encoding.upper() not in ("",'DEFAULT'):
+         GDebug.printMesg(1,'Setting postgresql client_encoding to %s' % 
encoding)
+         cursor = self.native.cursor()
+         cursor.execute("SET CLIENT_ENCODING TO '%s'" % encoding)
+         cursor.close()
+ 
+     except self._DatabaseError:
+       try:
+         cursor.close()
+       except:
+         pass
+ 
+     if connectData.has_key('datetimeformat'):
+       self._dateTimeFormat = "'%s'" % connectData['datetimeformat']
+     else:
+       self._dateTimeFormat = "'%Y-%m-%d %H:%M:%S'"
+ 
+ 
+   #########
+   #
+   # Extensions to the basic GConnection object
+   #
+ 
+   # Return the current date, according to database
+   def getTimeStamp(self):
+     return self.__singleQuery("select current_timestamp")
+ 
+   # Return a sequence number from sequence 'name'
+   def getSequence(self, name):
+     return self.__singleQuery("select nextval('%s')" % name)
+ 
+   # Run the SQL statement 'statement'
+   def sql(self, statement):
+     cursor = self.native.cursor()
+     try:
+       cursor.execute(statement)
+       cursor.close()
+     except:
+       cursor.close()
+       raise
+ 
+   # Used internally
+   def __singleQuery(self, statement):
+     cursor = self.native.cursor()
+     try:
+       cursor.execute(statement)
+       rv = cursor.fetchone()
+       cursor.close()
+     except:
+       print "DBdriver.py", "You've got your bar in my foo! And you've got 
your foo on my bar!  Two great reams that ream well together!"
+       GDebug.printMesg(1,"**** Unable to execute extension query")
+       GDebug.printMesg(1,"**** %s" % sys.exc_info()[1])
+       cursor.close()
+       raise
+ 
+     try:
+       return rv[0]
+     except:
+       return None
Index: gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:57 2003
--- gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py   Thu Oct 
 9 21:21:26 2003
***************
*** 0 ****
--- 1,45 ----
+ #
+ # 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:
+ # _pgsql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # A core Postgresql dbdriver that the other (specific)
+ # postgresql drivers can extend
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['DataObject_SQL','DataObject_Object']
+ 
+ 
+ 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'"
+ 
Index: gnue-common/src/datasources/drivers/postgresql/Base/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/Base/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:58 2003
--- gnue-common/src/datasources/drivers/postgresql/Base/RecordSet.py    Thu Oct 
 9 21:21:26 2003
***************
*** 0 ****
--- 1,61 ----
+ #
+ # 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:
+ # _pgsql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # A core Postgresql dbdriver that the other (specific)
+ # postgresql drivers can extend
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['RecordSet']
+ 
+ import string
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ 
+ #
+ #
+ #
+ class RecordSet(DBSIG2.RecordSet):
+   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 ') )
+ 
+ 
Index: gnue-common/src/datasources/drivers/postgresql/Base/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/Base/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:58 2003
--- gnue-common/src/datasources/drivers/postgresql/Base/ResultSet.py    Thu Oct 
 9 21:21:26 2003
***************
*** 0 ****
--- 1,42 ----
+ #
+ # 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:
+ # _pgsql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # A core Postgresql dbdriver that the other (specific)
+ # postgresql drivers can extend
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['ResultSet']
+ 
+ from gnue.common.datasources.drivers import DBSIG2
+ from RecordSet import RecordSet
+ 
+ #
+ #
+ #
+ class ResultSet(DBSIG2.ResultSet):
+   _recordSetClass = RecordSet
+ 
+ 
Index: gnue-common/src/datasources/drivers/postgresql/Base/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/Base/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:58 2003
--- gnue-common/src/datasources/drivers/postgresql/Base/__init__.py     Thu Oct 
 9 21:21:26 2003
***************
*** 0 ****
--- 1,25 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ from DataObject import *
+ from ResultSet import *
+ from RecordSet import *
Index: 
gnue-common/src/datasources/drivers/postgresql/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:59 2003
--- 
gnue-common/src/datasources/drivers/postgresql/Schema/Discovery/Introspection.py
    Thu Oct  9 21:21:27 2003
***************
*** 0 ****
--- 1,188 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('view',_('Views'),1),
+            ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     includeTables = (type in ('table','sources', None))
+     includeViews = (type in ('view','sources', None))
+ 
+     inClause = []
+     if includeTables:
+       inClause.append ("'r'")
+     if includeViews:
+       inClause.append ("'v'")
+ 
+     # TODO: This excludes any system tables and views. Should it?
+     statement = "select relname, relkind, oid from pg_class " + \
+             "where relkind in (%s) " % (join(inClause,',')) + \
+             "and relname not like 'pg_%' " + \
+             "order by relname"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[2], 'name':rs[0],
+                          'type':rs[1] == 'v' and 'view' or 'table',
+                          'primarykey': self.__getPrimaryKey(cursor, rs[2])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # TODO: Merge into find()
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     statement = "select relname, relkind, oid from pg_class " + \
+             "where relname = '%s'" % (name)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs:
+       schema = GDataObjects.Schema(attrs={'id':rs[2], 'name':rs[0],
+                            'type':rs[1] == 'v' and 'view' or 'table',
+                            'primarykey': self.__getPrimaryKey(cursor, rs[2]) 
},
+                            getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+   def __getPrimaryKey(self, cursor, oid):
+     cursor = self._dataConnection.cursor()
+     cursor.execute("select indkey from pg_index where indrelid=%s" % oid)
+     rs = cursor.fetchone()
+     statement = "select attname from pg_attribute " \
+                 "where attrelid = %s and attnum = %%s" % oid
+     if rs:
+       pks = []
+       for indpos in string.split(rs[0]):
+         cursor.execute(statement % int(indpos))
+         pks.append(cursor.fetchone()[0])
+       cursor.close()
+       return tuple(pks)
+     else:
+       cursor.close()
+       return None
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     statement = "select attname, pg_type.oid, typname, " + \
+             " attnotnull, atthasdef, atttypmod, attnum, attlen " + \
+             "from pg_attribute, pg_type " + \
+             "where attrelid = %s and " % (parent.id) + \
+             "pg_type.oid = atttypid and attnum >= 0" + \
+             "order by attnum"
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[1], 'name': rs[0],
+              'type':'field', 'nativetype': rs[2],
+              'required': rs[3] and not rs[4]}
+ 
+       if rs[2] in 
('numeric','float4','float8','money','bool','int8','int2','int4'):
+         attrs['datatype']='number'
+       elif rs[2] in ('date','time','timestamp','abstime','reltime'):
+         attrs['datatype']='date'
+       else:
+         attrs['datatype']='text'
+ 
+       if rs[7] > 0:
+         attrs['length'] = rs[7]
+       elif rs[5] != -1: #text field
+         attrs['length'] = rs[5] - 4
+ 
+ 
+       # Find any default values
+       if rs[4]:
+         cursor.execute("select adsrc " + \
+                        "from pg_attrdef " + \
+                        "where adrelid = %s and adnum = %s" % (parent.id, 
rs[6]))
+         defrs = cursor.fetchone()
+         if defrs:
+           dflt = defrs[0]
+           if dflt[:8] == 'nextval(':
+             attrs['defaulttype'] = 'sequence'
+             attrs['defaultval'] = split(dflt,"'")[1]
+           elif dflt == 'now()':
+             attrs['defaulttype'] = 'system'
+             attrs['defaultval'] = 'timestamp'
+           else:
+             attrs['defaulttype'] = 'constant'
+             attrs['defaultval'] = dflt
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return list
+ 
+ 
Index: gnue-common/src/datasources/drivers/postgresql/popy/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/popy/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:59 2003
--- gnue-common/src/datasources/drivers/postgresql/popy/__init__.py     Thu Oct 
 9 21:21:28 2003
***************
*** 0 ****
--- 1,44 ----
+ #
+ # 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:
+ # popy/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Postgresql implementation of dbdriver using Python DB-SIG v2
+ # specification.
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ('Connection')
+ 
+ from gnue.common.datasources.drivers.postgresql import Base
+ import PoPy
+ 
+ class Connection(Base.Connection):
+   _pg_driver = PoPy
+ 
+ 
+ 
+ __description__ = _("PoPy Data Driver for PostgreSQL")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/postgresql/psycopg/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/psycopg/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:59 2003
--- gnue-common/src/datasources/drivers/postgresql/psycopg/__init__.py  Thu Oct 
 9 21:21:28 2003
***************
*** 0 ****
--- 1,43 ----
+ #
+ # 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:
+ # psycopg/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Postgresql implementation of dbdriver using Python DB-SIG v2
+ # specification.
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ('Connection')
+ 
+ from gnue.common.datasources.drivers.postgresql import Base
+ import psycopg
+ 
+ class Connection(Base.Connection):
+   _pg_driver = psycopg
+ 
+ 
+ __description__ = _("Psycopg Data Driver for PostgreSQL")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/postgresql/pygresql/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/pygresql/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:59 2003
--- gnue-common/src/datasources/drivers/postgresql/pygresql/__init__.py Thu Oct 
 9 21:21:28 2003
***************
*** 0 ****
--- 1,81 ----
+ #
+ # 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:
+ # postgresql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Postgresql implementation of dbdriver using Python DB-SIG v2
+ # specification.
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ('Connection')
+ 
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ 
+ try:
+   import pgdb
+   from _pg import error as PGError   # This is so we can catch login errors
+ except ImportError, message:
+   tmsg = _("Driver not installed: pygresql for PostgreSQL [%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ from gnue.common.datasources.drivers.postgresql import Base
+ 
+ 
+ class Connection(Base.Connection):
+   _pg_driver = PoPy
+   _DatabaseError = pgdb.Error
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Postgresql database driver initializing")
+     try:
+       self.native = pgdb.connect(user=connectData['_username'],
+                    password=connectData['_password'],
+                    host=connectData['host'],
+                    database=connectData['dbname'])
+     except PGError, value:
+       raise GDataObjects.LoginError, value
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     try:
+       encoding = connectData['encoding']
+       GDebug.printMesg(1,'Setting postgresql client_encoding to %s' % 
encoding)
+       cursor = self.native.cursor()
+       cursor.execute("SET CLIENT_ENCODING TO '%s'" % encoding)
+       cursor.close()
+     except KeyError:
+       pass
+     except self._DatabaseError:
+       try:
+         cursor.close()
+       except:
+         pass
+ 
+ 
+ 
+ __description__ = _("PyGreSQL Data Driver for PostgreSQL")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/postgresql/pypgsql/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/postgresql/pypgsql/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:21:59 2003
--- gnue-common/src/datasources/drivers/postgresql/pypgsql/__init__.py  Thu Oct 
 9 21:21:29 2003
***************
*** 0 ****
--- 1,105 ----
+ #
+ # 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:
+ # pypgsql/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Postgresql implementation of dbdriver using Python DB-SIG v2
+ # specification.
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ('Connection')
+ 
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.postgresql.Base.Driver \
+    import PGSQL_RecordSet, PGSQL_ResultSet, PGSQL_DataObject, \
+           PGSQL_DataObject_SQL, PGSQL_DataObject_Object, \
+           PGSQL_TriggerExtensions
+ 
+ try:
+   from pyPgSQL import PgSQL # pyPgSQL 2.0 support
+ except ImportError:
+   import PgSQL              # pyPgSQL 1.6 support
+ 
+ 
+ 
+ class ResultSet(Base.ResultSet):
+ 
+   # TODO: Override the base _loadNextRecord as the fetchmany() from the cursor
+   # TODO: returns an exception instead of None.  Not sure wazzup with that.
+   def _loadNextRecord(self):
+     if self._cursor:
+       rs = None
+ 
+       try:
+         rsets = self._cursor.fetchmany()
+       except self._dataObject._DatabaseError, err:
+         rsets = None
+       except:
+         rsets = None
+ 
+       if rsets and len(rsets):
+         for rs in(rsets):
+           if rs:
+             i = 0
+             dict = {}
+             for f in (rs):
+               dict[self._fieldNames[i]] = f
+               i += 1
+             self._cachedRecords.append (self._recordSetClass(parent=self, \
+                                                              
initialData=dict))
+           else:
+             return 0
+         return 1
+       else:
+         return 0
+     else:
+       return 0
+ 
+ 
+ 
+ class DataObject_Object(Base.DataObject_Object)
+   _resultSetClass = PG_ResultSet
+ 
+ 
+ class DataObject_SQL(Base.DataObject_SQL)
+   _resultSetClass = PG_ResultSet
+ 
+ 
+ class Connection(Base.Connection):
+   _pg_driver = PgSQL
+   _pg_connectString = '%s::%s:%s:%s::%s'
+ 
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+ 
+ 
+ __description__ = _("PyPGsql Data Driver for PostgreSQL")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: 
gnue-common/src/datasources/drivers/sapdb/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sapdb/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:00 2003
--- gnue-common/src/datasources/drivers/sapdb/Schema/Discovery/Introspection.py 
Thu Oct  9 21:21:30 2003
***************
*** 0 ****
--- 1,193 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('table',    _('Tables'),1),
+            ('view',     _('Views'), 1),
+            ('synonym',  _('Synonyms'),1),
+            ('result',   _('Result Table'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = "where TYPE <> 'SYSTEM' and TYPE <> 'SYNONYM' "
+     else:
+       where_type = "where TYPE='%s'" % string.upper(type)
+ 
+ 
+     statement = \
+       "select owner||'.'||tablename||'.'||type, " + \
+         "owner||'.'||tablename table_name, " + \
+         "type table_type " + \
+         "from domain.tables %s" \
+               % (where_type) + \
+           "order by tablename "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rs[1],
+                          'type':string.lower(rs[2])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     where_user = ""
+     parts = string.split(string.upper(name),'.')
+     name = parts[-1]
+     if len(parts) > 1:
+       schema = " and owner='%s'" % parts[-2]
+     else:
+       schema = ""
+ 
+     statement = \
+       "select owner||'.'||tablename||'.'||type, " + \
+         "owner||'.'||tablename table_name, " + \
+         "type table_type, " + \
+         "owner, tablename " + \
+         "from domain.tables where tablename='%s'%s" \
+               % (name, schema) + \
+           "order by tablename "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self.native.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':string.lower(rs[0]), 
'name':rs[1],
+                          'type':rs[2], 'sapdbId': (rs [3], rs [4])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+ 
+     try:
+       return list[0]
+     except:
+       return None
+ 
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: This does not support user-defined datatypes...
+     # TODO: it will always report such as TEXT-like fields.
+ 
+     schema, name, type = string.split(parent.id,'.')
+     owner, basename = parent.sapdbId
+     cursor = self.native.cursor()
+ 
+ #    if type == 'synonym':
+ #      statement = "select base_tabschema, base_tabname " + \
+ #                  "from syscat.tables " + \
+ #                  "where tabschema = '%s' and tabname='%s'" % (schema, name)
+ #
+ #      GDebug.printMesg(5,statement)
+ #
+ #      cursor.execute(statement)
+ #      rs = cursor.fetchone()
+ #      schema, name = rs
+ 
+     statement = \
+        "select owner||'.'||tablename||'.'||columnname, " + \
+        "columnname, datatype, 'Y', len, dec " + \
+        "from domain.columns " + \
+        "where owner = '%s' and tablename = '%s' " % (owner, basename) + \
+        'order by "POS"'
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': rs[1],
+              'type':'field', 'nativetype': rs[2],
+              'required': 'N'}
+ 
+       if rs[2] in ('BOOLEAN','FIXED','FLOAT','INTEGER','LONG','SMALLINT'):
+         attrs['precision'] = rs[5]
+         attrs['datatype'] = 'number'
+       elif rs[2] in ('DATE','TIME','TIMESTAMP'):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+ 
+       if rs[5] != 0:
+         attrs['length'] = rs[4]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
Index: gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:01 2003
--- gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py       Thu Oct 
 9 21:21:30 2003
***************
*** 0 ****
--- 1,128 ----
+ #
+ # 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:
+ # sapdb/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SAP's SAP-DB/Python Driver
+ # Requires SAP-DB (http://www.sapdb.org/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the SAP-DB host for your connection (optional)
+ #     dbname=    This is the SAP-DB database to use (required)
+ #     timeout=   Command timeout in seconds (optional)
+ #     isolation= Isolation level (options)
+ #     sqlmode=   INTERNAl or ORACLE (optional)
+ #     sqlsubmode= ODBC or empty (optional)
+ #
+ 
+ _exampleConfig = """
+ # This connection uses the SAP DB  driver
+ # We will be connecting to the SAP DB server on
+ # "localhost" to a database called "TST".
+ [sapdb]
+ comment = XYZ Development Database
+ provider = sapdb
+ dbname = TST
+ # host = localhost   # (optional)
+ # sqlmode = INTERNAL # (default) or ORACLE
+ # sqlsubmode = ODBC  # (for compatibility with the SAP DB ODBC driver)
+ # timeout = 900      # (command timeout in seconds)
+ # isolation = 1      # 0, 1 (default), 10, 15, 2, 20, 3, 30
+ """
+ 
+ __all__ = ['Connection']
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ import string
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ try:
+   import sapdbapi as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: sapdbapi for SAP-DB 7.x \n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ from gnue.common.datasources.drivers.sapdb.Schema.Discovery.Introspection 
import Introspection
+ 
+ 
+ ######################################################################
+ #
+ #  GConnection object for PostgreSQL-based drivers
+ #
+ class Connection(DBSIG2.Connection):
+ 
+   _DatabaseError = SIG2api.DatabaseError
+   _defaultBehavior = Introspection
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SAP database driver initializing")
+     try:
+       options = {'autocommit': 'off'}
+       for gnueName, sapdbName in [('sqlmode', 'sqlmode'),
+                                   ('timeout', 'timeout'),
+                                   ('isolation', 'isolation'),
+                                   ('sqlsubmode', 'component')]:
+           if connectData.has_key (gnueName):
+               options [sapdbName] = connectData [gnueName]
+       self.native = apply (SIG2api.connect,
+         (connectData['_username'], connectData['_password'],
+         connectData['dbname'], connectData.get ('host', '')),
+         options)
+       #self.native = SIG2api.connect( \
+       #             user=connectData['_username'], \
+       #             password=connectData['_password'], \
+       #             database=connectData['dbname'], \
+       #             host=connectData.get ('host', ''), \
+       #             autocommit="off")
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+ 
+ def createConnection (conn, **overrides):
+     from gnue.common.datasources.GConnections import GConnections
+     connections = GConnections (r'D:\Python22\etc\connections.conf')
+     parameters = connections.getConnectionParameters (conn).copy ()
+     dataObject = connections.getDataObject (conn, 'object')
+     parameters.update (overrides)
+     dataObject.connect (parameters)
+     return dataObject
+ 
+ def testConnection ():
+     conn, user, pwd = sys.argv [1:4]
+     connection = createConnection (conn, _username = user, _password = pwd)
+     connection.getSchemaList ()
+ 
+ if __name__ == "__main__":
+     testConnection ()
Index: gnue-common/src/datasources/drivers/sapdb/sapdb/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sapdb/sapdb/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:01 2003
--- gnue-common/src/datasources/drivers/sapdb/sapdb/DataObject.py       Thu Oct 
 9 21:21:30 2003
***************
*** 0 ****
--- 1,325 ----
+ #
+ # 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:
+ # sapdb/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SAP's SAP-DB/Python Driver
+ # Requires SAP-DB (http://www.sapdb.org/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the SAP-DB host for your connection (optional)
+ #     dbname=    This is the SAP-DB database to use (required)
+ #     timeout=   Command timeout in seconds (optional)
+ #     isolation= Isolation level (options)
+ #     sqlmode=   INTERNAl or ORACLE (optional)
+ #     sqlsubmode= ODBC or empty (optional)
+ #
+ 
+ _exampleConfig = """
+ # This connection uses the SAP DB  driver
+ # We will be connecting to the SAP DB server on
+ # "localhost" to a database called "TST".
+ [sapdb]
+ comment = XYZ Development Database
+ provider = sapdb
+ dbname = TST
+ # host = localhost   # (optional)
+ # sqlmode = INTERNAL # (default) or ORACLE
+ # sqlsubmode = ODBC  # (for compatibility with the SAP DB ODBC driver)
+ # timeout = 900      # (command timeout in seconds)
+ # isolation = 1      # 0, 1 (default), 10, 15, 2, 20, 3, 30
+ """
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ import string
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import sapdbapi as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: sapdbapi for SAP-DB 7.x \n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ class SAP_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SAP_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SAP_RecordSet
+ 
+ 
+ 
+ class SAP_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SAP_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SAP database driver initializing")
+     try:
+       options = {'autocommit': 'off'}
+       for gnueName, sapdbName in [('sqlmode', 'sqlmode'),
+                                   ('timeout', 'timeout'),
+                                   ('isolation', 'isolation'),
+                                   ('sqlsubmode', 'component')]:
+           if connectData.has_key (gnueName):
+               options [sapdbName] = connectData [gnueName]
+       self._dataConnection = apply (SIG2api.connect,
+         (connectData['_username'], connectData['_password'],
+         connectData['dbname'], connectData.get ('host', '')),
+         options)
+       #self._dataConnection = SIG2api.connect( \
+       #             user=connectData['_username'], \
+       #             password=connectData['_password'], \
+       #             database=connectData['dbname'], \
+       #             host=connectData.get ('host', ''), \
+       #             autocommit="off")
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [ ('table',    _('Tables'),1),
+              ('view',     _('Views'), 1),
+              ('synonym',  _('Synonyms'),1),
+              ('result',   _('Result Table'),1) ]
+ 
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = "where TYPE <> 'SYSTEM' and TYPE <> 'SYNONYM' "
+     else:
+       where_type = "where TYPE='%s'" % string.upper(type)
+ 
+ 
+     statement = \
+       "select owner||'.'||tablename||'.'||type, " + \
+         "owner||'.'||tablename table_name, " + \
+         "type table_type " + \
+         "from domain.tables %s" \
+               % (where_type) + \
+           "order by tablename "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rs[1],
+                          'type':string.lower(rs[2])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     where_user = ""
+     parts = string.split(string.upper(name),'.')
+     name = parts[-1]
+     if len(parts) > 1:
+       schema = " and owner='%s'" % parts[-2]
+     else:
+       schema = ""
+ 
+     statement = \
+       "select owner||'.'||tablename||'.'||type, " + \
+         "owner||'.'||tablename table_name, " + \
+         "type table_type, " + \
+         "owner, tablename " + \
+         "from domain.tables where tablename='%s'%s" \
+               % (name, schema) + \
+           "order by tablename "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':string.lower(rs[0]), 
'name':rs[1],
+                          'type':rs[2], 'sapdbId': (rs [3], rs [4])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+ 
+     try:
+       return list[0]
+     except:
+       return None
+ 
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: This does not support user-defined datatypes...
+     # TODO: it will always report such as TEXT-like fields.
+ 
+     schema, name, type = string.split(parent.id,'.')
+     owner, basename = parent.sapdbId
+     cursor = self._dataConnection.cursor()
+ 
+ #    if type == 'synonym':
+ #      statement = "select base_tabschema, base_tabname " + \
+ #                  "from syscat.tables " + \
+ #                  "where tabschema = '%s' and tabname='%s'" % (schema, name)
+ #
+ #      GDebug.printMesg(5,statement)
+ #
+ #      cursor.execute(statement)
+ #      rs = cursor.fetchone()
+ #      schema, name = rs
+ 
+     statement = \
+        "select owner||'.'||tablename||'.'||columnname, " + \
+        "columnname, datatype, 'Y', len, dec " + \
+        "from domain.columns " + \
+        "where owner = '%s' and tablename = '%s' " % (owner, basename) + \
+        'order by "POS"'
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': rs[1],
+              'type':'field', 'nativetype': rs[2],
+              'required': 'N'}
+ 
+       if rs[2] in ('BOOLEAN','FIXED','FLOAT','INTEGER','LONG','SMALLINT'):
+         attrs['precision'] = rs[5]
+         attrs['datatype'] = 'number'
+       elif rs[2] in ('DATE','TIME','TIMESTAMP'):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+ 
+       if rs[5] != 0:
+         attrs['length'] = rs[4]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
+ 
+ class SAP_DataObject_Object(SAP_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SAP_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class SAP_DataObject_SQL(SAP_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SAP_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SAP_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasource "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SAP_DataObject_Object,
+   'sql':    SAP_DataObject_SQL
+ }
+ 
+ def createConnection (conn, **overrides):
+     from gnue.common.datasources.GConnections import GConnections
+     connections = GConnections (r'D:\Python22\etc\connections.conf')
+     parameters = connections.getConnectionParameters (conn).copy ()
+     dataObject = connections.getDataObject (conn, 'object')
+     parameters.update (overrides)
+     dataObject.connect (parameters)
+     return dataObject
+ 
+ def testConnection ():
+     conn, user, pwd = sys.argv [1:4]
+     connection = createConnection (conn, _username = user, _password = pwd)
+     connection.getSchemaList ()
+ 
+ if __name__ == "__main__":
+     testConnection ()
Index: gnue-common/src/datasources/drivers/sapdb/sapdb/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sapdb/sapdb/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:02 2003
--- gnue-common/src/datasources/drivers/sapdb/sapdb/RecordSet.py        Thu Oct 
 9 21:21:30 2003
***************
*** 0 ****
--- 1,325 ----
+ #
+ # 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:
+ # sapdb/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SAP's SAP-DB/Python Driver
+ # Requires SAP-DB (http://www.sapdb.org/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the SAP-DB host for your connection (optional)
+ #     dbname=    This is the SAP-DB database to use (required)
+ #     timeout=   Command timeout in seconds (optional)
+ #     isolation= Isolation level (options)
+ #     sqlmode=   INTERNAl or ORACLE (optional)
+ #     sqlsubmode= ODBC or empty (optional)
+ #
+ 
+ _exampleConfig = """
+ # This connection uses the SAP DB  driver
+ # We will be connecting to the SAP DB server on
+ # "localhost" to a database called "TST".
+ [sapdb]
+ comment = XYZ Development Database
+ provider = sapdb
+ dbname = TST
+ # host = localhost   # (optional)
+ # sqlmode = INTERNAL # (default) or ORACLE
+ # sqlsubmode = ODBC  # (for compatibility with the SAP DB ODBC driver)
+ # timeout = 900      # (command timeout in seconds)
+ # isolation = 1      # 0, 1 (default), 10, 15, 2, 20, 3, 30
+ """
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ import string
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import sapdbapi as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: sapdbapi for SAP-DB 7.x \n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ class SAP_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SAP_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SAP_RecordSet
+ 
+ 
+ 
+ class SAP_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SAP_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SAP database driver initializing")
+     try:
+       options = {'autocommit': 'off'}
+       for gnueName, sapdbName in [('sqlmode', 'sqlmode'),
+                                   ('timeout', 'timeout'),
+                                   ('isolation', 'isolation'),
+                                   ('sqlsubmode', 'component')]:
+           if connectData.has_key (gnueName):
+               options [sapdbName] = connectData [gnueName]
+       self._dataConnection = apply (SIG2api.connect,
+         (connectData['_username'], connectData['_password'],
+         connectData['dbname'], connectData.get ('host', '')),
+         options)
+       #self._dataConnection = SIG2api.connect( \
+       #             user=connectData['_username'], \
+       #             password=connectData['_password'], \
+       #             database=connectData['dbname'], \
+       #             host=connectData.get ('host', ''), \
+       #             autocommit="off")
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [ ('table',    _('Tables'),1),
+              ('view',     _('Views'), 1),
+              ('synonym',  _('Synonyms'),1),
+              ('result',   _('Result Table'),1) ]
+ 
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = "where TYPE <> 'SYSTEM' and TYPE <> 'SYNONYM' "
+     else:
+       where_type = "where TYPE='%s'" % string.upper(type)
+ 
+ 
+     statement = \
+       "select owner||'.'||tablename||'.'||type, " + \
+         "owner||'.'||tablename table_name, " + \
+         "type table_type " + \
+         "from domain.tables %s" \
+               % (where_type) + \
+           "order by tablename "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rs[1],
+                          'type':string.lower(rs[2])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     where_user = ""
+     parts = string.split(string.upper(name),'.')
+     name = parts[-1]
+     if len(parts) > 1:
+       schema = " and owner='%s'" % parts[-2]
+     else:
+       schema = ""
+ 
+     statement = \
+       "select owner||'.'||tablename||'.'||type, " + \
+         "owner||'.'||tablename table_name, " + \
+         "type table_type, " + \
+         "owner, tablename " + \
+         "from domain.tables where tablename='%s'%s" \
+               % (name, schema) + \
+           "order by tablename "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':string.lower(rs[0]), 
'name':rs[1],
+                          'type':rs[2], 'sapdbId': (rs [3], rs [4])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+ 
+     try:
+       return list[0]
+     except:
+       return None
+ 
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: This does not support user-defined datatypes...
+     # TODO: it will always report such as TEXT-like fields.
+ 
+     schema, name, type = string.split(parent.id,'.')
+     owner, basename = parent.sapdbId
+     cursor = self._dataConnection.cursor()
+ 
+ #    if type == 'synonym':
+ #      statement = "select base_tabschema, base_tabname " + \
+ #                  "from syscat.tables " + \
+ #                  "where tabschema = '%s' and tabname='%s'" % (schema, name)
+ #
+ #      GDebug.printMesg(5,statement)
+ #
+ #      cursor.execute(statement)
+ #      rs = cursor.fetchone()
+ #      schema, name = rs
+ 
+     statement = \
+        "select owner||'.'||tablename||'.'||columnname, " + \
+        "columnname, datatype, 'Y', len, dec " + \
+        "from domain.columns " + \
+        "where owner = '%s' and tablename = '%s' " % (owner, basename) + \
+        'order by "POS"'
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': rs[1],
+              'type':'field', 'nativetype': rs[2],
+              'required': 'N'}
+ 
+       if rs[2] in ('BOOLEAN','FIXED','FLOAT','INTEGER','LONG','SMALLINT'):
+         attrs['precision'] = rs[5]
+         attrs['datatype'] = 'number'
+       elif rs[2] in ('DATE','TIME','TIMESTAMP'):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+ 
+       if rs[5] != 0:
+         attrs['length'] = rs[4]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
+ 
+ class SAP_DataObject_Object(SAP_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SAP_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class SAP_DataObject_SQL(SAP_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SAP_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SAP_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasource "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SAP_DataObject_Object,
+   'sql':    SAP_DataObject_SQL
+ }
+ 
+ def createConnection (conn, **overrides):
+     from gnue.common.datasources.GConnections import GConnections
+     connections = GConnections (r'D:\Python22\etc\connections.conf')
+     parameters = connections.getConnectionParameters (conn).copy ()
+     dataObject = connections.getDataObject (conn, 'object')
+     parameters.update (overrides)
+     dataObject.connect (parameters)
+     return dataObject
+ 
+ def testConnection ():
+     conn, user, pwd = sys.argv [1:4]
+     connection = createConnection (conn, _username = user, _password = pwd)
+     connection.getSchemaList ()
+ 
+ if __name__ == "__main__":
+     testConnection ()
Index: gnue-common/src/datasources/drivers/sapdb/sapdb/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sapdb/sapdb/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:02 2003
--- gnue-common/src/datasources/drivers/sapdb/sapdb/ResultSet.py        Thu Oct 
 9 21:21:30 2003
***************
*** 0 ****
--- 1,325 ----
+ #
+ # 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:
+ # sapdb/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SAP's SAP-DB/Python Driver
+ # Requires SAP-DB (http://www.sapdb.org/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the SAP-DB host for your connection (optional)
+ #     dbname=    This is the SAP-DB database to use (required)
+ #     timeout=   Command timeout in seconds (optional)
+ #     isolation= Isolation level (options)
+ #     sqlmode=   INTERNAl or ORACLE (optional)
+ #     sqlsubmode= ODBC or empty (optional)
+ #
+ 
+ _exampleConfig = """
+ # This connection uses the SAP DB  driver
+ # We will be connecting to the SAP DB server on
+ # "localhost" to a database called "TST".
+ [sapdb]
+ comment = XYZ Development Database
+ provider = sapdb
+ dbname = TST
+ # host = localhost   # (optional)
+ # sqlmode = INTERNAL # (default) or ORACLE
+ # sqlsubmode = ODBC  # (for compatibility with the SAP DB ODBC driver)
+ # timeout = 900      # (command timeout in seconds)
+ # isolation = 1      # 0, 1 (default), 10, 15, 2, 20, 3, 30
+ """
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ import string
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import sapdbapi as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: sapdbapi for SAP-DB 7.x \n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ class SAP_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SAP_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SAP_RecordSet
+ 
+ 
+ 
+ class SAP_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SAP_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SAP database driver initializing")
+     try:
+       options = {'autocommit': 'off'}
+       for gnueName, sapdbName in [('sqlmode', 'sqlmode'),
+                                   ('timeout', 'timeout'),
+                                   ('isolation', 'isolation'),
+                                   ('sqlsubmode', 'component')]:
+           if connectData.has_key (gnueName):
+               options [sapdbName] = connectData [gnueName]
+       self._dataConnection = apply (SIG2api.connect,
+         (connectData['_username'], connectData['_password'],
+         connectData['dbname'], connectData.get ('host', '')),
+         options)
+       #self._dataConnection = SIG2api.connect( \
+       #             user=connectData['_username'], \
+       #             password=connectData['_password'], \
+       #             database=connectData['dbname'], \
+       #             host=connectData.get ('host', ''), \
+       #             autocommit="off")
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [ ('table',    _('Tables'),1),
+              ('view',     _('Views'), 1),
+              ('synonym',  _('Synonyms'),1),
+              ('result',   _('Result Table'),1) ]
+ 
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     where_user = ""
+     if type == None:
+       where_type = "where TYPE <> 'SYSTEM' and TYPE <> 'SYNONYM' "
+     else:
+       where_type = "where TYPE='%s'" % string.upper(type)
+ 
+ 
+     statement = \
+       "select owner||'.'||tablename||'.'||type, " + \
+         "owner||'.'||tablename table_name, " + \
+         "type table_type " + \
+         "from domain.tables %s" \
+               % (where_type) + \
+           "order by tablename "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rs[1],
+                          'type':string.lower(rs[2])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     where_user = ""
+     parts = string.split(string.upper(name),'.')
+     name = parts[-1]
+     if len(parts) > 1:
+       schema = " and owner='%s'" % parts[-2]
+     else:
+       schema = ""
+ 
+     statement = \
+       "select owner||'.'||tablename||'.'||type, " + \
+         "owner||'.'||tablename table_name, " + \
+         "type table_type, " + \
+         "owner, tablename " + \
+         "from domain.tables where tablename='%s'%s" \
+               % (name, schema) + \
+           "order by tablename "
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor = self._dataConnection.cursor()
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       list.append(GDataObjects.Schema(attrs={'id':string.lower(rs[0]), 
'name':rs[1],
+                          'type':rs[2], 'sapdbId': (rs [3], rs [4])},
+                          getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+ 
+     try:
+       return list[0]
+     except:
+       return None
+ 
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     # TODO: This does not support user-defined datatypes...
+     # TODO: it will always report such as TEXT-like fields.
+ 
+     schema, name, type = string.split(parent.id,'.')
+     owner, basename = parent.sapdbId
+     cursor = self._dataConnection.cursor()
+ 
+ #    if type == 'synonym':
+ #      statement = "select base_tabschema, base_tabname " + \
+ #                  "from syscat.tables " + \
+ #                  "where tabschema = '%s' and tabname='%s'" % (schema, name)
+ #
+ #      GDebug.printMesg(5,statement)
+ #
+ #      cursor.execute(statement)
+ #      rs = cursor.fetchone()
+ #      schema, name = rs
+ 
+     statement = \
+        "select owner||'.'||tablename||'.'||columnname, " + \
+        "columnname, datatype, 'Y', len, dec " + \
+        "from domain.columns " + \
+        "where owner = '%s' and tablename = '%s' " % (owner, basename) + \
+        'order by "POS"'
+ 
+     GDebug.printMesg(5,statement)
+ 
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+ 
+       attrs={'id': rs[0], 'name': rs[1],
+              'type':'field', 'nativetype': rs[2],
+              'required': 'N'}
+ 
+       if rs[2] in ('BOOLEAN','FIXED','FLOAT','INTEGER','LONG','SMALLINT'):
+         attrs['precision'] = rs[5]
+         attrs['datatype'] = 'number'
+       elif rs[2] in ('DATE','TIME','TIMESTAMP'):
+         attrs['datatype'] = 'date'
+       else:
+         attrs['datatype'] = 'text'
+ 
+       if rs[5] != 0:
+         attrs['length'] = rs[4]
+ 
+       list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     cursor.close()
+     return tuple(list)
+ 
+ 
+ class SAP_DataObject_Object(SAP_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SAP_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class SAP_DataObject_SQL(SAP_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SAP_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SAP_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasource "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SAP_DataObject_Object,
+   'sql':    SAP_DataObject_SQL
+ }
+ 
+ def createConnection (conn, **overrides):
+     from gnue.common.datasources.GConnections import GConnections
+     connections = GConnections (r'D:\Python22\etc\connections.conf')
+     parameters = connections.getConnectionParameters (conn).copy ()
+     dataObject = connections.getDataObject (conn, 'object')
+     parameters.update (overrides)
+     dataObject.connect (parameters)
+     return dataObject
+ 
+ def testConnection ():
+     conn, user, pwd = sys.argv [1:4]
+     connection = createConnection (conn, _username = user, _password = pwd)
+     connection.getSchemaList ()
+ 
+ if __name__ == "__main__":
+     testConnection ()
Index: gnue-common/src/datasources/drivers/sapdb/sapdb/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sapdb/sapdb/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:02 2003
--- gnue-common/src/datasources/drivers/sapdb/sapdb/__init__.py Thu Oct  9 
21:21:30 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("SAP-DB Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/special/configfile/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/special/configfile/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:03 2003
--- gnue-common/src/datasources/drivers/special/configfile/__init__.py  Thu Oct 
 9 21:21:31 2003
***************
*** 0 ****
--- 1,6 ----
+ from Driver import *
+ 
+ __description__ = _("ConfigFile Special Data Driver")
+ __driverurl__ = "n/a"
+ __examples__ = "n/a"
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/special/static/Driver.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/special/static/Driver.py:1.9.2.1
*** /dev/null   Thu Oct  9 21:22:03 2003
--- gnue-common/src/datasources/drivers/special/static/Driver.py        Thu Oct 
 9 21:21:31 2003
***************
*** 0 ****
--- 1,159 ----
+ #
+ # 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 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # _static/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Virtual database driver for a connectionless, static set of data
+ #
+ # NOTES:
+ # Used whenever a fixed set of data is needed
+ #
+ 
+ from gnue.common.apps import GDebug
+ import string
+ from gnue.common.datasources.GDataObjects import *
+ 
+ 
+ ###########################################################
+ #
+ # This is an static data driver for connectionless clients
+ # 
+ ###########################################################
+ class STATIC_DataObject (DataObject): 
+ 
+   def _createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
sql=""):
+     return STATIC_ResultSet(self, masterRecordSet=masterRecordSet)
+ 
+   # We don't do logins
+   def getLoginFields(self):
+     return ()
+ 
+   # We don't do connections (we are connectionless)
+   def connect(self, connectData={}):
+     # build field list
+     self._fieldReferences=string.split(self._staticSet.fields,",")
+ 
+     self._postConnect()
+ 
+   # We don't do commits
+   def commit(self):
+     pass
+ 
+   # And we don't do rollbacks
+   def rollback(self):
+     pass
+ 
+ 
+ 
+ ###########################################################
+ #
+ #
+ #
+ ###########################################################
+ class STATIC_ResultSet(ResultSet):
+ 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     
+     self._recordSetClass = STATIC_RecordSet
+ 
+   # Returns 1=DataObject has uncommitted changes
+   def isPending(self):
+     return 0    # Static DataObjects cannot have pending changes :)
+ 
+   # Post changes to the database
+   def post(self):
+     # Leave this here in case (for some bizarro reason)
+     # a bound dataobject uses us as a master
+     for record in (self._cachedRecords):
+       record.post()
+ 
+   # Load cacheCount number of new records
+   def _loadNextRecord(self):
+     if hasattr(self,"_alldataloaded"):
+       return 0
+     
+     # Load static data
+     for row in self._dataObject._staticSet._children:
+       dict = {}
+       for field in row._children:
+         dict[field.name] = field.value
+ 
+       record=self._recordSetClass(parent=self,initialData=dict)
+       
+       self._cachedRecords.append (record)
+       
+       self._recordCount=self._recordCount+1
+ 
+     self._alldataloaded = 1
+       
+     return 1
+ 
+ 
+   # Create an empty record
+   def _createEmptyRecord(self, masterRecordSet=None): 
+     return self._recordSetClass(self, None)
+ 
+ 
+ ###########################################################
+ # 
+ #
+ # 
+ ###########################################################
+ class STATIC_RecordSet (RecordSet): 
+ 
+   def isPending(self):
+     return 0
+ 
+   # Post any changes to database
+   def _postChanges(self): 
+     return 1
+ 
+   
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #  
+ class TriggerExtensions: 
+   def __init__(self, connection): 
+     self.__connection = connection
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': STATIC_DataObject
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/special/static/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/special/static/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:03 2003
--- gnue-common/src/datasources/drivers/special/static/__init__.py      Thu Oct 
 9 21:21:31 2003
***************
*** 0 ****
--- 1,6 ----
+ from Driver import *
+ 
+ __description__ = _("Static Special Data Driver")
+ __driverurl__ = "n/a"
+ __examples__ = "n/a"
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/special/unbound/Driver.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/special/unbound/Driver.py:1.6.2.1
*** /dev/null   Thu Oct  9 21:22:03 2003
--- gnue-common/src/datasources/drivers/special/unbound/Driver.py       Thu Oct 
 9 21:21:31 2003
***************
*** 0 ****
--- 1,142 ----
+ #
+ # 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 2001-2003 Free Software Foundation
+ #
+ # FILE:
+ # _empty/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Virtual database driver for a dataless/connectionless client
+ #
+ # NOTES:
+ # Primarily used by unbound forms blocks
+ #
+ 
+ from gnue.common.apps import GDebug
+ import string
+ from gnue.common.datasources.GDataObjects import * 
+ 
+ 
+ ###########################################################
+ #
+ # This is an empty data driver for connectionless clients
+ # (primarily used by forms)
+ # 
+ ###########################################################
+ class NIL_DataObject (DataObject): 
+ 
+   def _createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
sql=""): 
+     return NIL_ResultSet(self, masterRecordSet=masterRecordSet)
+ 
+   # We don't do logins
+   def getLoginFields(self):
+     return ()
+ 
+   # We don't do connections (we are connectionless)
+   def connect(self, connectData={}):
+     self._postConnect()
+ 
+   # We don't do commits
+   def commit(self):
+     pass
+ 
+   # And we don't do rollbacks
+   def rollback(self):
+     pass
+ 
+ 
+ 
+ ###########################################################
+ #
+ # 
+ # 
+ ###########################################################
+ class NIL_ResultSet(ResultSet): 
+ 
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None): 
+     ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = NIL_RecordSet
+ 
+ 
+   # Returns 1=DataObject has uncommitted changes 
+   def isPending(self):
+     return 0    # Empty DataObjects cannot have pending changes :)
+ 
+   # Post changes to the database
+   def post(self):
+     # Leave this here in case (for some bizarro reason)
+     # a bound dataobject uses us as a master
+     for record in (self._cachedRecords): 
+       record.post()
+ 
+   # Returns 1=Field is bound to a database field
+   def isFieldBound(self, fieldName):
+     return 0
+ 
+   # Load cacheCount number of new records
+   def _loadNextRecord(self): 
+     return 0
+ 
+ 
+   # Create an empty record
+   def _createEmptyRecord(self): 
+     return self._recordSetClass(self)
+ 
+ 
+ ###########################################################
+ # 
+ #
+ # 
+ ###########################################################
+ class NIL_RecordSet (RecordSet): 
+ 
+   def isPending(self):
+     return 0
+ 
+   # Post any changes to database
+   def _postChanges(self): 
+     return 1
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #  
+ class TriggerExtensions: 
+   def __init__(self, connection): 
+     self.__connection = connection
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe 
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ # 
+ supportedDataObjects = { 
+   'object': NIL_DataObject
+ }
+ 
+ 
Index: gnue-common/src/datasources/drivers/special/unbound/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/special/unbound/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:03 2003
--- gnue-common/src/datasources/drivers/special/unbound/__init__.py     Thu Oct 
 9 21:21:31 2003
***************
*** 0 ****
--- 1,6 ----
+ from Driver import *
+ 
+ __description__ = _("Unbound Special Data Driver")
+ __driverurl__ = "n/a"
+ __examples__ = "n/a"
+ __doc__ = ""
Index: 
gnue-common/src/datasources/drivers/sqlite/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlite/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:04 2003
--- 
gnue-common/src/datasources/drivers/sqlite/Schema/Discovery/Introspection.py    
    Thu Oct  9 21:21:32 2003
***************
*** 0 ****
--- 1,190 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('view',_('Views'),1),
+            ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+ 
+     if type!=None:
+       where=" WHERE type='%s'" % type
+     else:
+       where=""
+ 
+     statement = "SELECT type,name,tbl_name,sql FROM master "+\
+                 where+" UNION ALL "+\
+                 "SELECT type,name,tbl_name,sql FROM temp_master "+\
+                 where+" ORDER BY name;"
+ 
+     cursor = self.native.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     list = []
+     for rs in cursor.fetchall():
+       if rs[0] in ('table','view'):
+         list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                                'type':rs[0],},
+                                         getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     print list
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+ 
+     if type!=None:
+       where=" AND type='%s'" % type
+     else:
+       where=""
+ 
+     statement = ("SELECT type,name,tbl_name,sql FROM master "+\
+                  "WHERE name='%s'"+where+" UNION ALL "+\
+                  "SELECT type,name,tbl_name,sql FROM temp_master "+\
+                  "WHERE name='%s' "+where+" ORDER BY name;") % (name,name)
+ 
+     cursor = self.native.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs and rs[0] in ('table','view'):
+       schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                           'type':rs[0],},
+                                    getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     if parent.type=='view':
+       print "Views are not supported at the moment"
+       return None
+ 
+     statement = ("SELECT type,name,tbl_name,sql FROM master "+\
+                  "WHERE type='%s' and name='%s' UNION ALL "+\
+                  "SELECT type,name,tbl_name,sql FROM temp_master "+\
+                  "WHERE type='%s' "+\
+                  "and name='%s' ORDER BY name;") % (parent.type,parent.id,\
+                                                     parent.type,parent.id)
+ 
+     cursor = self.native.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+     columns = cursor.description
+ 
+     # Because sqlite don't store column definitions, but computes it
+     # every time anew from the 'create table' statement, we have to
+     # parse that statement to get the data
+ 
+     # get sql definition of table
+     rs = cursor.fetchone()
+     cursor.close()
+     if rs:
+       sql=rs[3]
+     else:
+       return None
+ 
+     # parse the sql definition
+     GDebug.printMesg(3,"** Table definition: %s **" % sql)
+ 
+     sql=sql[find(sql,'(')+1:rfind(sql,')')]
+     fields = split(sql,',')
+     list = []
+     for field in fields:
+ 
+       fls=split(strip(field),' ',2)
+ 
+       if not fls[0] in ('Constraint','Primary'):
+         
+         try:
+           nativetype= fls[1][:find(fls[1],'(')]
+ 
+           size=int(fls[1][find(fls[1],'(')+1:-1])
+         except:
+           nativetype = fls[1]
+           size=None
+         
+         attrs={'id': "%s.%s" % (parent.id, fls[0]), 'name': fls[0],
+                'type':'field', 'nativetype': nativetype,
+                'required':fls[2]=="NOT NULL"}
+         
+         if size!=None:
+           attrs['length'] = size
+         
+         if nativetype in ('int','integer','bigint','mediumint',
+                            'smallint','tinyint','float','real',
+                            'double','decimal'):
+           attrs['datatype']='number'
+         elif nativetype[0] in ('date','time','timestamp','datetime'):
+           attrs['datatype']='date'
+         else:
+           attrs['datatype']='text'
+ 
+         list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     return list
+ 
Index: gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:04 2003
--- gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py     Thu Oct 
 9 21:21:33 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:
+ # SQLitedb/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SQLite's Python Driver.
+ # Requires PySQLite (http://pysqlite.sf.net/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     dbname=    This is the SQLite database to use (required)
+ #
+ 
+ __all__ = ['Connection']
+ 
+ from string import lower,find,rfind,split,strip
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ try:
+   import sqlite as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: SQLitedbapi for SQLite 7.x \n[%s]") % 
message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ from gnue.common.datasources.drivers.sqlite.Schema.Discovery.Introspection 
import Introspection
+ 
+ 
+ ######################################################################
+ #
+ #  GConnection object for PostgreSQL-based drivers
+ #
+ class Connection(DBSIG2.Connection):
+ 
+   _DatabaseError = SIG2api.DatabaseError
+   _defaultBehavior = Introspection
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SQLite database driver initializing")
+     try:
+       self.native = SIG2api.connect(  \
+                    db=connectData['dbname'], \
+                    mode=077 )
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+ 
+   # Return a list of necessary login fields (e.g., user/pass).
+   # Each list item is another list of ["field label", isPassword?]
+   def getLoginFields(self):
+     return []
+ 
+ 
Index: gnue-common/src/datasources/drivers/sqlite/sqlite/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlite/sqlite/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:04 2003
--- gnue-common/src/datasources/drivers/sqlite/sqlite/DataObject.py     Thu Oct 
 9 21:21:33 2003
***************
*** 0 ****
--- 1,278 ----
+ #
+ # 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:
+ # SQLitedb/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SQLite's Python Driver.
+ # Requires PySQLite (http://pysqlite.sf.net/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     dbname=    This is the SQLite database to use (required)
+ #
+ 
+ 
+ from string import lower,find,rfind,split,strip
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import sqlite as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: SQLitedbapi for SQLite 7.x \n[%s]") % 
message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class SQLite_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SQLite_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SQLite_RecordSet
+ 
+ 
+ 
+ class SQLite_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SQLite_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SQLite database driver initializing")
+     try:
+       self._dataConnection = SIG2api.connect(  \
+                    db=connectData['dbname'], \
+                    mode=077 )
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   # Return a list of necessary login fields (e.g., user/pass).
+   # Each list item is another list of ["field label", isPassword?]
+   def getLoginFields(self):
+     return []
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Table'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     
+     if type!=None:
+       where=" WHERE type='%s'" % type
+     else:
+       where=""
+ 
+     statement = "SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                 where+" UNION ALL "+\
+                 "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                 where+" ORDER BY name;"
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)    
+ 
+     list = []
+     for rs in cursor.fetchall():
+       if rs[0] in ('table','view'):
+         list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                                'type':rs[0],},
+                                         getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     print list
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     
+     if type!=None:
+       where=" AND type='%s'" % type
+     else:
+       where=""
+ 
+     statement = ("SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                  "WHERE name='%s'"+where+" UNION ALL "+\
+                  "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                  "WHERE name='%s' "+where+" ORDER BY name;") % (name,name)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs and rs[0] in ('table','view'):
+       schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                           'type':rs[0],},
+                                    getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     if parent.type=='view':
+       print "Views are not supported at the moment"
+       return None
+ 
+     statement = ("SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                  "WHERE type='%s' and name='%s' UNION ALL "+\
+                  "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                  "WHERE type='%s' "+\
+                  "and name='%s' ORDER BY name;") % (parent.type,parent.id,\
+                                                     parent.type,parent.id)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+     columns = cursor.description
+ 
+     # Because sqlite don't store column definitions, but computes it
+     # every time anew from the 'create table' statement, we have to
+     # parse that statement to get the data
+ 
+     # get sql definition of table
+     rs = cursor.fetchone()
+     cursor.close()
+     if rs:
+       sql=rs[3]
+     else:
+       return None
+ 
+     # parse the sql definition
+     GDebug.printMesg(3,"** Table definition: %s **" % sql)
+ 
+     sql=sql[find(sql,'(')+1:rfind(sql,')')]
+     fields = split(sql,',')
+     list = []
+     for field in fields:
+ 
+       fls=split(strip(field),' ',2)
+ 
+       if not fls[0] in ('Constraint','Primary'):
+         
+         try:
+           nativetype= fls[1][:find(fls[1],'(')]
+ 
+           size=int(fls[1][find(fls[1],'(')+1:-1])
+         except:
+           nativetype = fls[1]
+           size=None
+         
+         attrs={'id': "%s.%s" % (parent.id, fls[0]), 'name': fls[0],
+                'type':'field', 'nativetype': nativetype,
+                'required':fls[2]=="NOT NULL"}
+         
+         if size!=None:
+           attrs['length'] = size
+         
+         if nativetype in ('int','integer','bigint','mediumint',
+                            'smallint','tinyint','float','real',
+                            'double','decimal'):
+           attrs['datatype']='number'
+         elif nativetype[0] in ('date','time','timestamp','datetime'):
+           attrs['datatype']='date'
+         else:
+           attrs['datatype']='text'
+ 
+         list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     return list
+ 
+ 
+ class SQLite_DataObject_Object(SQLite_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SQLite_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail, 
additionalSQL)
+ 
+ 
+ class SQLite_DataObject_SQL(SQLite_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SQLite_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SQLite_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SQLite_DataObject_Object,
+   'sql':    SQLite_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sqlite/sqlite/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlite/sqlite/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:05 2003
--- gnue-common/src/datasources/drivers/sqlite/sqlite/RecordSet.py      Thu Oct 
 9 21:21:33 2003
***************
*** 0 ****
--- 1,278 ----
+ #
+ # 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:
+ # SQLitedb/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SQLite's Python Driver.
+ # Requires PySQLite (http://pysqlite.sf.net/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     dbname=    This is the SQLite database to use (required)
+ #
+ 
+ 
+ from string import lower,find,rfind,split,strip
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import sqlite as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: SQLitedbapi for SQLite 7.x \n[%s]") % 
message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class SQLite_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SQLite_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SQLite_RecordSet
+ 
+ 
+ 
+ class SQLite_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SQLite_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SQLite database driver initializing")
+     try:
+       self._dataConnection = SIG2api.connect(  \
+                    db=connectData['dbname'], \
+                    mode=077 )
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   # Return a list of necessary login fields (e.g., user/pass).
+   # Each list item is another list of ["field label", isPassword?]
+   def getLoginFields(self):
+     return []
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Table'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     
+     if type!=None:
+       where=" WHERE type='%s'" % type
+     else:
+       where=""
+ 
+     statement = "SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                 where+" UNION ALL "+\
+                 "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                 where+" ORDER BY name;"
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)    
+ 
+     list = []
+     for rs in cursor.fetchall():
+       if rs[0] in ('table','view'):
+         list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                                'type':rs[0],},
+                                         getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     print list
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     
+     if type!=None:
+       where=" AND type='%s'" % type
+     else:
+       where=""
+ 
+     statement = ("SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                  "WHERE name='%s'"+where+" UNION ALL "+\
+                  "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                  "WHERE name='%s' "+where+" ORDER BY name;") % (name,name)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs and rs[0] in ('table','view'):
+       schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                           'type':rs[0],},
+                                    getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     if parent.type=='view':
+       print "Views are not supported at the moment"
+       return None
+ 
+     statement = ("SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                  "WHERE type='%s' and name='%s' UNION ALL "+\
+                  "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                  "WHERE type='%s' "+\
+                  "and name='%s' ORDER BY name;") % (parent.type,parent.id,\
+                                                     parent.type,parent.id)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+     columns = cursor.description
+ 
+     # Because sqlite don't store column definitions, but computes it
+     # every time anew from the 'create table' statement, we have to
+     # parse that statement to get the data
+ 
+     # get sql definition of table
+     rs = cursor.fetchone()
+     cursor.close()
+     if rs:
+       sql=rs[3]
+     else:
+       return None
+ 
+     # parse the sql definition
+     GDebug.printMesg(3,"** Table definition: %s **" % sql)
+ 
+     sql=sql[find(sql,'(')+1:rfind(sql,')')]
+     fields = split(sql,',')
+     list = []
+     for field in fields:
+ 
+       fls=split(strip(field),' ',2)
+ 
+       if not fls[0] in ('Constraint','Primary'):
+         
+         try:
+           nativetype= fls[1][:find(fls[1],'(')]
+ 
+           size=int(fls[1][find(fls[1],'(')+1:-1])
+         except:
+           nativetype = fls[1]
+           size=None
+         
+         attrs={'id': "%s.%s" % (parent.id, fls[0]), 'name': fls[0],
+                'type':'field', 'nativetype': nativetype,
+                'required':fls[2]=="NOT NULL"}
+         
+         if size!=None:
+           attrs['length'] = size
+         
+         if nativetype in ('int','integer','bigint','mediumint',
+                            'smallint','tinyint','float','real',
+                            'double','decimal'):
+           attrs['datatype']='number'
+         elif nativetype[0] in ('date','time','timestamp','datetime'):
+           attrs['datatype']='date'
+         else:
+           attrs['datatype']='text'
+ 
+         list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     return list
+ 
+ 
+ class SQLite_DataObject_Object(SQLite_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SQLite_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail, 
additionalSQL)
+ 
+ 
+ class SQLite_DataObject_SQL(SQLite_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SQLite_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SQLite_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SQLite_DataObject_Object,
+   'sql':    SQLite_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sqlite/sqlite/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlite/sqlite/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:05 2003
--- gnue-common/src/datasources/drivers/sqlite/sqlite/ResultSet.py      Thu Oct 
 9 21:21:33 2003
***************
*** 0 ****
--- 1,278 ----
+ #
+ # 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:
+ # SQLitedb/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SQLite's Python Driver.
+ # Requires PySQLite (http://pysqlite.sf.net/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     dbname=    This is the SQLite database to use (required)
+ #
+ 
+ 
+ from string import lower,find,rfind,split,strip
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import sqlite as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: SQLitedbapi for SQLite 7.x \n[%s]") % 
message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class SQLite_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SQLite_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SQLite_RecordSet
+ 
+ 
+ 
+ class SQLite_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SQLite_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SQLite database driver initializing")
+     try:
+       self._dataConnection = SIG2api.connect(  \
+                    db=connectData['dbname'], \
+                    mode=077 )
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+   # Return a list of necessary login fields (e.g., user/pass).
+   # Each list item is another list of ["field label", isPassword?]
+   def getLoginFields(self):
+     return []
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Table'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     
+     if type!=None:
+       where=" WHERE type='%s'" % type
+     else:
+       where=""
+ 
+     statement = "SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                 where+" UNION ALL "+\
+                 "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                 where+" ORDER BY name;"
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)    
+ 
+     list = []
+     for rs in cursor.fetchall():
+       if rs[0] in ('table','view'):
+         list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                                'type':rs[0],},
+                                         getChildSchema=self.__getFieldSchema))
+ 
+     cursor.close()
+     print list
+     return list
+ 
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     
+     if type!=None:
+       where=" AND type='%s'" % type
+     else:
+       where=""
+ 
+     statement = ("SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                  "WHERE name='%s'"+where+" UNION ALL "+\
+                  "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                  "WHERE name='%s' "+where+" ORDER BY name;") % (name,name)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+ 
+     rs = cursor.fetchone()
+     if rs and rs[0] in ('table','view'):
+       schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
+                                           'type':rs[0],},
+                                    getChildSchema=self.__getFieldSchema)
+     else:
+       schema = None
+ 
+     cursor.close()
+     return schema
+ 
+ 
+   # Get fields for a table
+   def __getFieldSchema(self, parent):
+ 
+     if parent.type=='view':
+       print "Views are not supported at the moment"
+       return None
+ 
+     statement = ("SELECT type,name,tbl_name,sql FROM sqlite_master "+\
+                  "WHERE type='%s' and name='%s' UNION ALL "+\
+                  "SELECT type,name,tbl_name,sql FROM sqlite_temp_master "+\
+                  "WHERE type='%s' "+\
+                  "and name='%s' ORDER BY name;") % (parent.type,parent.id,\
+                                                     parent.type,parent.id)
+ 
+     cursor = self._dataConnection.cursor()
+     GDebug.printMesg(1,"** Executing: %s **" % statement)
+     cursor.execute(statement)
+     columns = cursor.description
+ 
+     # Because sqlite don't store column definitions, but computes it
+     # every time anew from the 'create table' statement, we have to
+     # parse that statement to get the data
+ 
+     # get sql definition of table
+     rs = cursor.fetchone()
+     cursor.close()
+     if rs:
+       sql=rs[3]
+     else:
+       return None
+ 
+     # parse the sql definition
+     GDebug.printMesg(3,"** Table definition: %s **" % sql)
+ 
+     sql=sql[find(sql,'(')+1:rfind(sql,')')]
+     fields = split(sql,',')
+     list = []
+     for field in fields:
+ 
+       fls=split(strip(field),' ',2)
+ 
+       if not fls[0] in ('Constraint','Primary'):
+         
+         try:
+           nativetype= fls[1][:find(fls[1],'(')]
+ 
+           size=int(fls[1][find(fls[1],'(')+1:-1])
+         except:
+           nativetype = fls[1]
+           size=None
+         
+         attrs={'id': "%s.%s" % (parent.id, fls[0]), 'name': fls[0],
+                'type':'field', 'nativetype': nativetype,
+                'required':fls[2]=="NOT NULL"}
+         
+         if size!=None:
+           attrs['length'] = size
+         
+         if nativetype in ('int','integer','bigint','mediumint',
+                            'smallint','tinyint','float','real',
+                            'double','decimal'):
+           attrs['datatype']='number'
+         elif nativetype[0] in ('date','time','timestamp','datetime'):
+           attrs['datatype']='date'
+         else:
+           attrs['datatype']='text'
+ 
+         list.append(GDataObjects.Schema(attrs=attrs))
+ 
+     return list
+ 
+ 
+ class SQLite_DataObject_Object(SQLite_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SQLite_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail, 
additionalSQL)
+ 
+ 
+ class SQLite_DataObject_SQL(SQLite_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SQLite_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SQLite_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SQLite_DataObject_Object,
+   'sql':    SQLite_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sqlite/sqlite/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlite/sqlite/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:05 2003
--- gnue-common/src/datasources/drivers/sqlite/sqlite/__init__.py       Thu Oct 
 9 21:21:33 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("SQLite Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:05 2003
--- gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py Thu Oct 
 9 21:21:34 2003
***************
*** 0 ****
--- 1,90 ----
+ #
+ # 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:
+ # SQLRelay/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SQLRelay's Python Driver
+ # Requires SQLRelay + Python-DB Driver (http://www.firstworks.com/sqlrelay)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the SQLRelay host for your connection (required)
+ #                In the format hostname:port (or ipaddr:port)
+ #
+ 
+ __all__ = ['Connection']
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ 
+ try:
+   from SQLRelay import PySQLRDB as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: SQLRelay Python API\n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ from gnue.common.datasources.drivers.sqlrelay.Schema.Discovery.Introspection 
import Introspection
+ 
+ 
+ ######################################################################
+ #
+ #  GConnection object for PostgreSQL-based drivers
+ #
+ class Connection(DBSIG2.Connection):
+ 
+   _defaultBehavior = Introspection
+   _DatabaseError = SIG2api.DatabaseError
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SQLRelay database driver initializing")
+ 
+     try:
+       host, port = string.split(connectData['host'],':')
+       port = int(port)
+     except ValueError:
+       host = connectData['host']
+       port = 9000
+ 
+     try:
+       self.native = SIG2api.connect( host, port, '', \
+                    connectData['_username'], \
+                    connectData['_password'], \
+                    0,1)
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+ 
Index: gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:05 2003
--- gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/DataObject.py Thu Oct 
 9 21:21:34 2003
***************
*** 0 ****
--- 1,167 ----
+ #
+ # 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:
+ # SQLRelay/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SQLRelay's Python Driver
+ # Requires SQLRelay + Python-DB Driver (http://www.firstworks.com/sqlrelay)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the SQLRelay host for your connection (required)
+ #                In the format hostname:port (or ipaddr:port)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   from SQLRelay import PySQLRDB as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: SQLRelay Python API\n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class SQLRelay_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SQLRelay_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SQLRelay_RecordSet
+ 
+ 
+ 
+ class SQLRelay_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SQLRelay_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SQLRelay database driver initializing")
+ 
+     try: 
+       host, port = string.split(connectData['host'],':')
+       port = int(port)
+     except ValueError: 
+       host = connectData['host']
+       port = 9000
+ 
+     try:
+       self._dataConnection = SIG2api.connect( host, port, '', \
+                    connectData['_username'], \
+                    connectData['_password'], \
+                    0,1)
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class SQLRelay_DataObject_Object(SQLRelay_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SQLRelay_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class SQLRelay_DataObject_SQL(SQLRelay_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SQLRelay_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SQLRelay_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SQLRelay_DataObject_Object,
+   'sql':    SQLRelay_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:05 2003
--- gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/RecordSet.py  Thu Oct 
 9 21:21:34 2003
***************
*** 0 ****
--- 1,167 ----
+ #
+ # 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:
+ # SQLRelay/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SQLRelay's Python Driver
+ # Requires SQLRelay + Python-DB Driver (http://www.firstworks.com/sqlrelay)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the SQLRelay host for your connection (required)
+ #                In the format hostname:port (or ipaddr:port)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   from SQLRelay import PySQLRDB as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: SQLRelay Python API\n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class SQLRelay_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SQLRelay_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SQLRelay_RecordSet
+ 
+ 
+ 
+ class SQLRelay_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SQLRelay_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SQLRelay database driver initializing")
+ 
+     try: 
+       host, port = string.split(connectData['host'],':')
+       port = int(port)
+     except ValueError: 
+       host = connectData['host']
+       port = 9000
+ 
+     try:
+       self._dataConnection = SIG2api.connect( host, port, '', \
+                    connectData['_username'], \
+                    connectData['_password'], \
+                    0,1)
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class SQLRelay_DataObject_Object(SQLRelay_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SQLRelay_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class SQLRelay_DataObject_SQL(SQLRelay_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SQLRelay_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SQLRelay_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SQLRelay_DataObject_Object,
+   'sql':    SQLRelay_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:05 2003
--- gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/ResultSet.py  Thu Oct 
 9 21:21:34 2003
***************
*** 0 ****
--- 1,167 ----
+ #
+ # 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:
+ # SQLRelay/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via SQLRelay's Python Driver
+ # Requires SQLRelay + Python-DB Driver (http://www.firstworks.com/sqlrelay)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     host=      This is the SQLRelay host for your connection (required)
+ #                In the format hostname:port (or ipaddr:port)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   from SQLRelay import PySQLRDB as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: SQLRelay Python API\n[%s]") % message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class SQLRelay_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class SQLRelay_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = SQLRelay_RecordSet
+ 
+ 
+ 
+ class SQLRelay_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = SQLRelay_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"SQLRelay database driver initializing")
+ 
+     try: 
+       host, port = string.split(connectData['host'],':')
+       port = int(port)
+     except ValueError: 
+       host = connectData['host']
+       port = 9000
+ 
+     try:
+       self._dataConnection = SIG2api.connect( host, port, '', \
+                    connectData['_username'], \
+                    connectData['_password'], \
+                    0,1)
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class SQLRelay_DataObject_Object(SQLRelay_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     SQLRelay_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class SQLRelay_DataObject_SQL(SQLRelay_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because SQLRelay_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     SQLRelay_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': SQLRelay_DataObject_Object,
+   'sql':    SQLRelay_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:06 2003
--- gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/__init__.py   Thu Oct 
 9 21:21:34 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("SQLRelay Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""
Index: 
gnue-common/src/datasources/drivers/sybase/Schema/Discovery/Introspection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sybase/Schema/Discovery/Introspection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:06 2003
--- 
gnue-common/src/datasources/drivers/sybase/Schema/Discovery/Introspection.py    
    Thu Oct  9 21:21:35 2003
***************
*** 0 ****
--- 1,75 ----
+ #
+ # 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:
+ # Introspection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Introspection']
+ 
+ import string
+ from string import lower, join, split
+ import sys
+ 
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import GIntrospection
+ 
+ class Introspection(GIntrospection.Introspection):
+ 
+   # list of the types of Schema objects this driver provides
+   types =[ ('view',_('Views'),1),
+            ('table',_('Tables'),1) ]
+ 
+   #
+   # TODO: This is a quick hack to get this class
+   # TODO: into the new-style schema format.
+   # TODO: getSchema* should be merged into find()
+   #
+   def find(self, name=None, type=None):
+     if name is None:
+       return self.getSchemaList(type)
+     else:
+       rs = self.getSchemaByName(name, type)
+       if rs:
+         return [rs]
+       else:
+         return None
+ 
+ 
+   # TODO: Merge into find()
+   # Return a list of Schema objects
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
Index: gnue-common/src/datasources/drivers/sybase/sybase/Connection.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sybase/sybase/Connection.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:06 2003
--- gnue-common/src/datasources/drivers/sybase/sybase/Connection.py     Thu Oct 
 9 21:21:35 2003
***************
*** 0 ****
--- 1,78 ----
+ #
+ # 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:
+ # sybase/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Dave Cole's Sybase ASE/Python Driver
+ # Requires Sybase.py (http://www.object-craft.com.au/projects/sybase/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Sybase DSN for your connection  (required)
+ #     dbame=      This is the Sybase database to use (optional)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ __all__ = ['Connection']
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers import DBSIG2
+ from DataObjects import *
+ 
+ try:
+   import Sybase as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Sybase.py for Sybase ASE 11.0/11.9 [%s]") % 
message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Connection(DBSIG2.Connection)
+   _DatabaseError = SIG2api.DatabaseError
+   _supportedDataObjects = {
+     'object': DataObject_Object,
+     'sql':    DataObject_SQL
+   }
+ 
+   def connect(self, connectData):
+     GDebug.printMesg(1,"Sybase database driver initializing")
+     try:
+       if connectData.has_key('dbname'):
+         self.native = SIG2api.connect( \
+                   service=connectData['service'],  \
+                   user=connectData['_username'], \
+                   passwd=connectData['_password'], \
+                   datbase=connectData['dbname'])
+       else:
+         self.native = SIG2api.connect( \
+                   service=connectData['service'],  \
+                   user=connectData['_username'], \
+                   passwd=connectData['_password'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
Index: gnue-common/src/datasources/drivers/sybase/sybase/DataObject.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sybase/sybase/DataObject.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:07 2003
--- gnue-common/src/datasources/drivers/sybase/sybase/DataObject.py     Thu Oct 
 9 21:21:35 2003
***************
*** 0 ****
--- 1,165 ----
+ #
+ # 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:
+ # sybase/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Dave Cole's Sybase ASE/Python Driver
+ # Requires Sybase.py (http://www.object-craft.com.au/projects/sybase/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Sybase DSN for your connection  (required)
+ #     dbame=      This is the Sybase database to use (optional)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import Sybase as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Sybase.py for Sybase ASE 11.0/11.9 [%s]") % 
message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Sybase_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Sybase_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Sybase_RecordSet
+ 
+ 
+ 
+ class Sybase_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Sybase_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Sybase database driver initializing")
+     try:
+       if connectData.has_key('dbname'):
+         self._dataConnection = SIG2api.connect( \
+                   service=connectData['service'],  \
+                   user=connectData['_username'], \
+                   passwd=connectData['_password'], \
+                   datbase=connectData['dbname'])
+       else:
+         self._dataConnection = SIG2api.connect( \
+                   service=connectData['service'],  \
+                   user=connectData['_username'], \
+                   passwd=connectData['_password'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Sybase_DataObject_Object(Sybase_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Sybase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class Sybase_DataObject_SQL(Sybase_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Sybase_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Sybase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Sybase_DataObject_Object,
+   'sql':    Sybase_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sybase/sybase/RecordSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sybase/sybase/RecordSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:07 2003
--- gnue-common/src/datasources/drivers/sybase/sybase/RecordSet.py      Thu Oct 
 9 21:21:35 2003
***************
*** 0 ****
--- 1,165 ----
+ #
+ # 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:
+ # sybase/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Dave Cole's Sybase ASE/Python Driver
+ # Requires Sybase.py (http://www.object-craft.com.au/projects/sybase/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Sybase DSN for your connection  (required)
+ #     dbame=      This is the Sybase database to use (optional)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import Sybase as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Sybase.py for Sybase ASE 11.0/11.9 [%s]") % 
message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Sybase_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Sybase_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Sybase_RecordSet
+ 
+ 
+ 
+ class Sybase_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Sybase_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Sybase database driver initializing")
+     try:
+       if connectData.has_key('dbname'):
+         self._dataConnection = SIG2api.connect( \
+                   service=connectData['service'],  \
+                   user=connectData['_username'], \
+                   passwd=connectData['_password'], \
+                   datbase=connectData['dbname'])
+       else:
+         self._dataConnection = SIG2api.connect( \
+                   service=connectData['service'],  \
+                   user=connectData['_username'], \
+                   passwd=connectData['_password'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Sybase_DataObject_Object(Sybase_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Sybase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class Sybase_DataObject_SQL(Sybase_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Sybase_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Sybase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Sybase_DataObject_Object,
+   'sql':    Sybase_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sybase/sybase/ResultSet.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sybase/sybase/ResultSet.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:07 2003
--- gnue-common/src/datasources/drivers/sybase/sybase/ResultSet.py      Thu Oct 
 9 21:21:35 2003
***************
*** 0 ****
--- 1,165 ----
+ #
+ # 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:
+ # sybase/DBdriver.py
+ #
+ # DESCRIPTION:
+ # Driver to provide access to data via Dave Cole's Sybase ASE/Python Driver
+ # Requires Sybase.py (http://www.object-craft.com.au/projects/sybase/)
+ #
+ # NOTES:
+ #
+ #   Supported attributes (via connections.conf or <database> tag)
+ #
+ #     service=    This is the Sybase DSN for your connection  (required)
+ #     dbame=      This is the Sybase database to use (optional)
+ #
+ 
+ #### THIS IS AN UNTESTED DRIVER ####
+ ####      Any volunteers?       ####
+ 
+ 
+ from string import lower
+ import sys
+ from gnue.common.datasources import GDataObjects, GConditions, GConnections
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources.drivers.DBSIG2.Driver \
+    import DBSIG2.RecordSet, DBSIG2.ResultSet, DBSIG2.DataObject, \
+           DBSIG2.DataObject_SQL, DBSIG2.DataObject_Object
+ 
+ try:
+   import Sybase as SIG2api
+ except ImportError, message:
+   tmsg = _("Driver not installed: Sybase.py for Sybase ASE 11.0/11.9 [%s]") % 
message
+   raise GConnections.AdapterNotInstalled, tmsg
+ 
+ 
+ class Sybase_RecordSet(DBSIG2.RecordSet):
+   pass
+ 
+ 
+ class Sybase_ResultSet(DBSIG2.ResultSet):
+   def __init__(self, dataObject, cursor=None, defaultValues={}, 
masterRecordSet=None):
+     DBSIG2.ResultSet.__init__(self, dataObject, \
+             cursor, defaultValues, masterRecordSet)
+     self._recordSetClass = Sybase_RecordSet
+ 
+ 
+ 
+ class Sybase_DataObject(DBSIG2.DataObject):
+   def __init__(self):
+     DBSIG2.DataObject.__init__(self)
+     self._DatabaseError = SIG2api.DatabaseError
+     self._resultSetClass = Sybase_ResultSet
+ 
+ 
+   def connect(self, connectData={}):
+     GDebug.printMesg(1,"Sybase database driver initializing")
+     try:
+       if connectData.has_key('dbname'):
+         self._dataConnection = SIG2api.connect( \
+                   service=connectData['service'],  \
+                   user=connectData['_username'], \
+                   passwd=connectData['_password'], \
+                   datbase=connectData['dbname'])
+       else:
+         self._dataConnection = SIG2api.connect( \
+                   service=connectData['service'],  \
+                   user=connectData['_username'], \
+                   passwd=connectData['_password'])
+     except self._DatabaseError, value:
+       raise GDataObjects.LoginError, value
+ 
+     self._postConnect()
+ 
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: See postgresql for an example of what these functions do.
+ 
+   # Return a list of the types of Schema objects this driver provides
+   def getSchemaTypes(self):
+     return [('view',_('Views'),1),
+             ('table',_('Tables'),1)]
+ 
+   # Return a list of Schema objects
+   def getSchemaList(self, type=None):
+     return []
+ 
+   # Find a schema object with specified name
+   def getSchemaByName(self, name, type=None):
+     return None
+ 
+   def _postConnect(self):
+     self.triggerExtensions = TriggerExtensions(self._dataConnection)
+ 
+ 
+ class Sybase_DataObject_Object(Sybase_DataObject, \
+       DBSIG2.DataObject_Object):
+ 
+   def __init__(self):
+     Sybase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
+     return DBSIG2.DataObject_Object._buildQuery(self, 
conditions,forDetail,additionalSQL)
+ 
+ 
+ class Sybase_DataObject_SQL(Sybase_DataObject, \
+       DBSIG2.DataObject_SQL):
+   def __init__(self):
+     # Call DBSIG init first because Sybase_DataObject needs to overwrite
+     # some of its values
+     DBSIG2.DataObject_SQL.__init__(self)
+     Sybase_DataObject.__init__(self)
+ 
+   def _buildQuery(self, conditions={}):
+     return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
+ 
+ 
+ #
+ #  Extensions to Trigger Namespaces
+ #
+ class TriggerExtensions:
+ 
+   def __init__(self, connection):
+     self.__connection = connection
+ 
+ 
+ 
+ 
+ ######################################
+ #
+ #  The following hashes describe
+ #  this driver's characteristings.
+ #
+ ######################################
+ 
+ #
+ #  All datasouce "types" and corresponding DataObject class
+ #
+ supportedDataObjects = {
+   'object': Sybase_DataObject_Object,
+   'sql':    Sybase_DataObject_SQL
+ }
+ 
Index: gnue-common/src/datasources/drivers/sybase/sybase/__init__.py
diff -c /dev/null 
gnue-common/src/datasources/drivers/sybase/sybase/__init__.py:1.1.2.1
*** /dev/null   Thu Oct  9 21:22:08 2003
--- gnue-common/src/datasources/drivers/sybase/sybase/__init__.py       Thu Oct 
 9 21:21:35 2003
***************
*** 0 ****
--- 1,27 ----
+ #
+ # 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
+ #
+ 
+ from Connection import *
+ 
+ __description__ = _("Sybase Data Driver")
+ __driverurl__ = "http://????";
+ __examples__ = ""
+ __doc__ = ""




reply via email to

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