[Top][All Lists]
[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__ = ""
- CVSROOT: /cvsroot/gnue,
Jason Cater <=