Author: johannes Date: 2005-06-02 09:32:55 -0500 (Thu, 02 Jun 2005) New Revision: 7573
Added: trunk/gnue-common/src/datasources/drivers/adodbapi/Behavior.py Removed: trunk/gnue-common/src/datasources/drivers/adodbapi/Schema/Discovery/ Modified: trunk/gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py Log: Replaced introspection by Behavior Added: trunk/gnue-common/src/datasources/drivers/adodbapi/Behavior.py =================================================================== --- trunk/gnue-common/src/datasources/drivers/adodbapi/Behavior.py 2005-06-02 08:33:38 UTC (rev 7572) +++ trunk/gnue-common/src/datasources/drivers/adodbapi/Behavior.py 2005-06-02 14:32:55 UTC (rev 7573) @@ -0,0 +1,185 @@ +# GNU Enterprise Common Library - ADO DB API - Schema Support +# +# Copyright 2001-2005 Free Software Foundation +# +# 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. +# +# $Id$ + +from gnue.common.datasources.drivers import Base +from gnue.common.datasources import GSchema + +# ============================================================================= +# This class implements schema support for ado db drivers +# ============================================================================= + +class Behavior (Base.Behavior): + + _RELKIND = {'TABLE': {'type': 'table', 'name': _('Tables')}, + 'VIEW' : {'type': 'view', 'name': _('Views')}} + + # --------------------------------------------------------------------------- + # Read the current connection's schema + # --------------------------------------------------------------------------- + + def _readSchema_ (self, parent): + """ + """ + + self._TYPEMAP = self.__buildTypeMap () + tables = self.__readTables (parent) + self.__readFields (tables) + self.__readPrimaryKeys (tables) + + + # --------------------------------------------------------------------------- + # Read all tables and views + # --------------------------------------------------------------------------- + + def __readTables (self, parent): + + result = {} + masters = {} + + rs = self.__connection._native.adoConn.OpenSchema (20) + + for rec in self.__iterateRS (rs): + (name, rtype) = [rec.get (i) for i in ['TABLE_NAME', 'TABLE_TYPE']] + + if not rtype in self._RELKIND: + continue + + if not rtype in masters: + masters [rtype] = GSchema.GSTables (parent, **self._RELKIND [rtype]) + + result [name] = GSchema.GSTable (masters [rtype], name = name) + + return result + + + # --------------------------------------------------------------------------- + # Read all fields for the given tables + # --------------------------------------------------------------------------- + + def __readFields (self, tables): + + result = {} + rs = self.__connection._native.adoConn.openSchema (4) + + for rec in self.__iterateRS (rs): + table = tables.get (rec ['TABLE_NAME']) + if table is None: + continue + + (group, datatype) = self._TYPEMAP.get (rec ['DATA_TYPE'], + self._TYPEMAP ['string']) + + parent = table.findChildOfType ('GSFields') or GSchema.GSFields (table) + attrs = {'id': '%s.%s' % (table.name, rec ['COLUMN_NAME']), + 'name': rec ['COLUMN_NAME'], + 'nativetype': rec ['DATA_TYPE'], + 'nullable': rec ['IS_NULLABLE'], + 'type': datatype} + + if group == 'string': + attrs ['length'] = int (rec ['CHARACTER_MAXIMUM_LENGTH'] or 0) + + elif group == 'number': + attrs ['length'] = rec ['NUMERIC_PRECISION'] + if attrs ['nativetype'] == self.__connection._driver.adCurrency: + attrs ['precision'] = 4 + else: + attrs ['precision'] = rec ['NUMERIC_SCALE'] + + result [attrs ['id']] = GSchema.GSField (parent, **attrs) + + return result + + + # --------------------------------------------------------------------------- + # Read all primary keys for the given tables + # --------------------------------------------------------------------------- + + def __readPrimaryKeys (self, tables): + + keys = {} + + rs = self.__connection._native.adoConn.OpenSchema (28) + for rec in self.__iterateRS (rs): + table = tables.get (rec ['TABLE_NAME']) + if table is None: + continue + + entry = keys.setdefault (table.name, {}) + entry ['name'] = rec.get ('PK_NAME') or 'pk_%s' % table.name + fields = entry.setdefault ('fields', []) + fields.append ((rec ['ORDINAL'], rec ['COLUMN_NAME'])) + + for (tname, keydef) in keys.items (): + table = tables [tname] + pk = GSchema.GSPrimaryKey (table, name = keydef ['name']) + fields = keydef ['fields'] + fields.sort () + + for (ix, name) in fields: + GSchema.GSPKField (pk, name = name) + + + # --------------------------------------------------------------------------- + # Iterate over a RecordSet and return every record as dictionary + # --------------------------------------------------------------------------- + + def __iterateRS (self, rs): + + if rs.BOF or rs.EOF: + return + + rs.MoveFirst () + + while not rs.EOF: + fld = rs.Fields + yield dict ([(fld (i).Name, fld (i).Value) for i in range (fld.Count)]) + + rs.MoveNext () + + + # --------------------------------------------------------------------------- + # Build a mapping for the supported datatypes + # --------------------------------------------------------------------------- + + def __buildTypeMap (self): + + dbm = self.__connection._driver + result = {'string': ('string', 'string'), + dbm.adBoolean: ('booelan', 'boolean'), + dbm.adDBTime: ('date', 'time')} + + for item in [dbm.adBigInt, dbm.adChapter, dbm.adCurrency, dbm.adDecimal, + dbm.adDouble, dbm.adInteger, dbm.adNumeric, dbm.adSingle, + dbm.adSmallInt, dbm.adTinyInt, dbm.adUnsignedBigInt, + dbm.adUnsignedInt, dbm.adUnsignedSmallInt, + dbm.adUnsignedTinyInt, dbm.adVarNumeric]: + result [item] = ('number', 'number') + + for item in [dbm.adDBDate, dbm.adDate]: + result [item] = ('date', 'date') + + for item in [dbm.adDBTimeStamp, dbm.adFileTime]: + result [item] = ('date', 'datetime'), + + return result Property changes on: trunk/gnue-common/src/datasources/drivers/adodbapi/Behavior.py ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py =================================================================== --- trunk/gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py 2005-06-02 08:33:38 UTC (rev 7572) +++ trunk/gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py 2005-06-02 14:32:55 UTC (rev 7573) @@ -26,7 +26,7 @@ import string from gnue.common.datasources.drivers import DBSIG2 -from gnue.common.datasources.drivers.adodbapi.Schema.Discovery.Introspection import Introspection +from gnue.common.datasources.drivers.adodbapi import Behavior # ============================================================================= @@ -42,7 +42,7 @@ _broken_rowcount = True - defaultBehavior = Introspection + defaultBehavior = Behavior.Behavior # --------------------------------------------------------------------------- @@ -51,6 +51,8 @@ def _getConnectParams (self, connectData): + import adodbapi + adodbapi.defaultIsolationLevel = adodbapi.adXactSerializable # mandatory parameters _______________________________________________ Commit-gnue mailing list Commit-gnue@gnu.org http://lists.gnu.org/mailman/listinfo/commit-gnue