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
38
raise "This data driver has not been upgraded to the new format."
44
class Gadfly_RecordSet(DBSIG2.RecordSet):
48
class Gadfly_ResultSet(DBSIG2.ResultSet):
49
def __init__(self, dataObject, cursor=None, defaultValues={}, masterRecordSet=None):
51
DBSIG2.ResultSet.__init__(self, dataObject, \
52
cursor, defaultValues, masterRecordSet)
53
self._recordSetClass = Gadfly_RecordSet
55
def _loadNextRecord(self):
60
rsets = self._cursor.fetchall()
61
except self._dataObject._connection._DatabaseError, err:
62
raise GDataObjects.ConnectionError, err
64
if rsets and len(rsets):
70
dict[string.lower(self._fieldNames[i])] = f
72
self._cachedRecords.append (self._recordSetClass(parent=self, \
83
class Error(StandardError):
86
class InterfaceError(Error):
89
class DatabaseError(InterfaceError):
92
class DataError(DatabaseError):
95
class OperationalError(DatabaseError):
96
"""Operational Error"""
98
class IntegrityError(DatabaseError):
103
class Gadfly_DataObject(DBSIG2.DataObject):
107
DBSIG2.DataObject.__init__(self)
108
self._DatabaseError = Error
109
self._resultSetClass = Gadfly_ResultSet
111
# LIKE is not supported on database level at the moment
112
# there should be used other ways to emulate it
113
# until that works, do a = instead of a like
115
self.conditionElements.update({\
116
'like': (2, 2, '%s = %s', None ),\
117
'notlike': (2, 2, 'NOT (%s = %s)', None )})
122
def connect(self, connectData={}):
123
gDebug(9,"Gadfly database driver initializing")
124
#GDebug.printMesg(1,"Connecting with %s, %s" %( connectData['_dbname'], connectData['directory']))
126
self._dataConnection = gadfly.gadfly(connectData['dbname'],
127
connectData['directory'])
128
except self._DatabaseError, value:
129
#GDebug.printMesg(1,"Boom")
130
raise GDataObjects.LoginError, value
132
self._beginTransaction()
136
def _postConnect(self):
137
self.triggerExtensions = TriggerExtensions(self._dataConnection)
140
def _beginTransaction(self):
142
self._dataConnection.begin()
146
# This should be over-ridden only if driver needs more than user/pass
147
def getLoginFields(self):
151
# Schema (metadata) functions
154
# Return a list of the types of Schema objects this driver provides
155
def getSchemaTypes(self):
156
return [('view',_('Views'),1),
157
('table',_('Tables'),1)]
159
# Return a list of Schema objects
160
def getSchemaList(self, type=None):
162
statement = "select * from __table_names__"
164
cursor = self._dataConnection.cursor()
165
GDebug.printMesg(1,"** Executing: %s **" % statement)
166
cursor.execute(statement)
169
for rs in cursor.fetchall():
170
# exclude any system tables and views. f.e. __table_names__
172
list.append(GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
173
'type':rs[0] == 1 and 'view' or 'table',},
174
getChildSchema=self.__getFieldSchema))
180
# Find a schema object with specified name
181
def getSchemaByName(self, name, type=None):
182
statement = "SELECT * from __table_names__ WHERE TABLE_NAME='%s'" % (name)
184
cursor = self._dataConnection.cursor()
185
GDebug.printMesg(1,"** Executing: %s **" % statement)
186
cursor.execute(statement)
188
rs = cursor.fetchone()
190
schema = GDataObjects.Schema(attrs={'id':rs[1], 'name':rs[1], \
191
'type':rs[0] == 1 and 'view' or 'table',},
192
getChildSchema=self.__getFieldSchema)
200
# Get fields for a table
201
def __getFieldSchema(self, parent):
203
# TODO: Read whole definitions from __DATADEFS__ and parse them
204
# to distinguish between varchar, float and integer
206
statement = "SELECT * FROM __COLUMNS__ WHERE TABLE_NAME='%s'" % parent.id
208
cursor = self._dataConnection.cursor()
209
GDebug.printMesg(1,"** Executing: %s **" % statement)
210
cursor.execute(statement)
211
columns = cursor.description
214
for rs in cursor.fetchall():
216
#nativetype = string.split(string.replace(rs[1],')',''),'(')
219
attrs={'id': "%s.%s" % (parent.id, rs[0]), 'name': rs[0],
220
'type':'field', 'nativetype': 'varchar',
223
#if nativetype[0] in ('int','integer','bigint','mediumint',
224
# 'smallint','tinyint','float','real',
225
# 'double','decimal'):
226
# attrs['datatype']='number'
227
#elif nativetype[0] in ('date','time','timestamp','datetime'):
228
# attrs['datatype']='date'
230
# attrs['datatype']='text'
233
attrs['datatype']='text'
237
# if len(nativetype) == 2:
238
# attrs['length'] = int(string.split(nativetype[1])[0])
240
# GDebug.printMesg(1,'WARNING: mysql native type error: %s' % nativetype)
242
list.append(GDataObjects.Schema(attrs=attrs))
250
class Gadfly_DataObject_Object(Gadfly_DataObject, \
251
DBSIG2.DataObject_Object):
254
Gadfly_DataObject.__init__(self)
256
def _buildQuery(self, conditions={},forDetail=None,additionalSQL=""):
257
return DBSIG2.DataObject_Object._buildQuery(self, conditions,forDetail,additionalSQL)
259
def _getQueryCount(self,conditions={}):
260
cursor = self._dataConnection.cursor()
262
cursor.execute(self._buildQueryCount(conditions))
263
# GADFLY throws an error if executing COUNT(*) on an empty set
265
rs = cursor.fetchone()
270
def _buildQueryCount(self, conditions={}):
271
# GADFLY seems to hate big letter "SELECT"
272
q = "select count(*) from %s%s" % (self.table, self._conditionToSQL(conditions))
274
GDebug.printMesg(5,q)
278
class Gadfly_DataObject_SQL(Gadfly_DataObject, \
279
DBSIG2.DataObject_SQL):
281
# Call DBSIG init first because Gadfly_DataObject needs to overwrite
283
DBSIG2.DataObject_SQL.__init__(self)
284
Gadfly_DataObject.__init__(self)
286
def _buildQuery(self, conditions={}):
287
return DBSIG2.DataObject_SQL._buildQuery(self, conditions)
292
# Extensions to Trigger Namespaces
294
class TriggerExtensions:
296
def __init__(self, connection):
297
self.__connection = connection
299
# Return the current date, according to database
303
# Return a sequence number from sequence 'name'
304
# def getSequence(self, name):
307
# Run the SQL statement 'statement'
308
# def sql(self, statement):
313
######################################
315
# The following hashes describe
316
# this driver's characteristings.
318
######################################
321
# All datasouce "types" and corresponding DataObject class
323
supportedDataObjects = {
324
'object': Gadfly_DataObject_Object,
325
'sql': Gadfly_DataObject_SQL