2
# This file is part of GNU Enterprise.
4
# GNU Enterprise is free software; you can redistribute it
5
# and/or modify it under the terms of the GNU General Public
6
# License as published by the Free Software Foundation; either
7
# version 2, or (at your option) any later version.
9
# GNU Enterprise is distributed in the hope that it will be
10
# useful, but WITHOUT ANY WARRANTY; without even the implied
11
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
# PURPOSE. See the GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public
15
# License along with program; see the file COPYING. If not,
16
# write to the Free Software Foundation, Inc., 59 Temple Place
17
# - Suite 330, Boston, MA 02111-1307, USA.
19
# Copyright 2000-2005 Free Software Foundation
25
# Driver to provide access to data via Gadfly
28
# The Gadfly notes state that it is not safe to use in a multi-user environment
29
# where there may be concurrent read/writes. Use at own risk :)
34
from gnue.common.apps import GDebug
35
from gnue.common.datasources import GDataObjects
36
from gnue.common.datasources.drivers import DBSIG2
40
raise "This data driver has not been upgraded to the new format."
42
class Gadfly_RecordSet(DBSIG2.RecordSet):
46
class Gadfly_ResultSet(DBSIG2.ResultSet):
47
def __init__(self, dataObject, cursor=None, defaultValues={}, masterRecordSet=None):
49
DBSIG2.ResultSet.__init__(self, dataObject, \
50
cursor, defaultValues, masterRecordSet)
51
self._recordSetClass = Gadfly_RecordSet
53
def _loadNextRecord(self):
58
rsets = self._cursor.fetchall()
59
except self._dataObject._connection._DatabaseError, err:
60
raise GDataObjects.ConnectionError, err
62
if rsets and len(rsets):
68
dict[string.lower(self._fieldNames[i])] = f
70
self._cachedRecords.append (self._recordSetClass(parent=self, \
81
class Error(StandardError):
84
class InterfaceError(Error):
87
class DatabaseError(InterfaceError):
90
class DataError(DatabaseError):
93
class OperationalError(DatabaseError):
94
"""Operational Error"""
96
class IntegrityError(DatabaseError):
101
class Gadfly_DataObject(DBSIG2.DataObject):
105
DBSIG2.DataObject.__init__(self)
106
self._DatabaseError = Error
107
self._resultSetClass = Gadfly_ResultSet
109
# LIKE is not supported on database level at the moment
110
# there should be used other ways to emulate it
111
# until that works, do a = instead of a like
113
self.conditionElements.update({\
114
'like': (2, 2, '%s = %s', None ),\
115
'notlike': (2, 2, 'NOT (%s = %s)', None )})
120
def connect(self, connectData={}):
121
gDebug(9,"Gadfly database driver initializing")
122
#GDebug.printMesg(1,"Connecting with %s, %s" %( connectData['_dbname'], connectData['directory']))
124
self._dataConnection = gadfly.gadfly(connectData['dbname'],
125
connectData['directory'])
126
except self._DatabaseError, value:
127
#GDebug.printMesg(1,"Boom")
128
raise GDataObjects.LoginError, value
130
self._beginTransaction()
134
def _postConnect(self):
135
self.triggerExtensions = TriggerExtensions(self._dataConnection)
138
def _beginTransaction(self):
140
self._dataConnection.begin()
144
# This should be over-ridden only if driver needs more than user/pass
145
def getLoginFields(self):
149
# Schema (metadata) functions
152
# Return a list of the types of Schema objects this driver provides
153
def getSchemaTypes(self):
154
return [('view',_('Views'),1),
155
('table',_('Tables'),1)]
157
# Return a list of Schema objects
158
def getSchemaList(self, type=None):
160
statement = "select * from __table_names__"
162
cursor = self._dataConnection.cursor()
163
GDebug.printMesg(1,"** Executing: %s **" % statement)
164
cursor.execute(statement)
167
for rs in cursor.fetchall():
168
# exclude any system tables and views. f.e. __table_names__
170
list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
171
'type':rs[0] == 1 and 'view' or 'table',},
172
getChildSchema=self.__getFieldSchema))
178
# Find a schema object with specified name
179
def getSchemaByName(self, name, type=None):
180
statement = "SELECT * from __table_names__ WHERE TABLE_NAME='%s'" % (name)
182
cursor = self._dataConnection.cursor()
183
GDebug.printMesg(1,"** Executing: %s **" % statement)
184
cursor.execute(statement)
186
rs = cursor.fetchone()
188
schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
189
'type':rs[0] == 1 and 'view' or 'table',},
190
getChildSchema=self.__getFieldSchema)
198
# Get fields for a table
199
def __getFieldSchema(self, parent):
201
# TODO: Read whole definitions from __DATADEFS__ and parse them
202
# to distinguish between varchar, float and integer
204
statement = "SELECT * FROM __COLUMNS__ WHERE TABLE_NAME='%s'" % parent.id
206
cursor = self._dataConnection.cursor()
207
GDebug.printMesg(1,"** Executing: %s **" % statement)
208
cursor.execute(statement)
209
columns = cursor.description
212
for rs in cursor.fetchall():
214
#nativetype = string.split(string.replace(rs[1],')',''),'(')
217
attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
218
'type':'field', 'nativetype': 'varchar',
221
#if nativetype[0] in ('int','integer','bigint','mediumint',
222
# 'smallint','tinyint','float','real',
223
# 'double','decimal'):
224
# attrs['datatype']='number'
225
#elif nativetype[0] in ('date','time','timestamp','datetime'):
226
# attrs['datatype']='date'
228
# attrs['datatype']='text'
231
attrs['datatype']='text'
235
# if len(nativetype) == 2:
236
# attrs['length'] = int(string.split(nativetype[1])[0])
238
# GDebug.printMesg(1,'WARNING: mysql native type error: %s' % nativetype)
240
list.append(GDataObjects.Schema(attrs=attrs))
248
class Gadfly_DataObject_Object(Gadfly_DataObject, \
249
DBSIG2.DataObject_Object):
252
Gadfly_DataObject.__init__(self)
254
def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
255
return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail,additionalSQL)
257
def _getQueryCount(self,conditions={}):
258
cursor = self._dataConnection.cursor()
260
cursor.execute(self._buildQueryCount(conditions))
261
# GADFLY throws an error if executing COUNT(*) on an empty set
263
rs = cursor.fetchone()
268
def _buildQueryCount(self, conditions={}):
269
# GADFLY seems to hate big letter "SELECT"
270
q = "select count(*) from %s%s" % (self.table, self._conditionToSQL(conditions))
272
GDebug.printMesg(5,q)
276
class Gadfly_DataObject_SQL(Gadfly_DataObject, \
277
DBSIG2.DataObject_SQL):
279
# Call DBSIG init first because Gadfly_DataObject needs to overwrite
281
DBSIG2.DataObject_SQL.__init__(self)
282
Gadfly_DataObject.__init__(self)
284
def _buildQuery(self, conditions={}):
285
return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
290
# Extensions to Trigger Namespaces
292
class TriggerExtensions:
294
def __init__(self, connection):
295
self.__connection = connection
297
# Return the current date, according to database
301
# Return a sequence number from sequence 'name'
302
# def getSequence(self, name):
305
# Run the SQL statement 'statement'
306
# def sql(self, statement):
311
######################################
313
# The following hashes describe
314
# this driver's characteristings.
316
######################################
319
# All datasouce "types" and corresponding DataObject class
321
supportedDataObjects = {
322
'object': Gadfly_DataObject_Object,
323
'sql': Gadfly_DataObject_SQL