##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
'''$Id: db.py 40218 2005-11-18 14:39:19Z andreasjung $'''
__version__='$Revision: 1.14 $'[11:-2]
import os
from string import strip, split
import gadfly
import Globals, Shared.DC.ZRDB.THUNK
from DateTime import DateTime
data_dir=os.path.join(Globals.data_dir,'gadfly')
from Products.ZGadflyDA import GadflyError, QueryError
def manage_DataSources():
if not os.path.exists(data_dir):
try:
os.mkdir(data_dir)
os.mkdir(os.path.join(data_dir,'demo'))
except:
raise GadflyError, (
"""
The Zope Gadfly Database Adapter requires the
existence of the directory, %s
. An error
occurred while trying to create this directory.
""" % data_dir)
if not os.path.isdir(data_dir):
raise GadflyError, (
"""
The Zope Gadfly Database Adapter requires the
existence of the directory, %s
. This
exists, but is not a directory.
""" % data_dir)
return map(
lambda d: (d,''),
filter(lambda f, i=os.path.isdir, d=data_dir, j=os.path.join:
i(j(d,f)),
os.listdir(data_dir))
)
class DB(Shared.DC.ZRDB.THUNK.THUNKED_TM):
database_error=gadfly.error
opened=''
def tables(self,*args,**kw):
if self.db is None: self.open()
return map(
lambda name: {
'TABLE_NAME': name,
'TABLE_TYPE': 'TABLE',
},
filter(self.db.database.datadefs.has_key, self.db.table_names())
)
def columns(self, table_name):
if self.db is None: self.open()
return map(lambda col: {
'Name': col.colid, 'Type': col.datatype, 'Precision': 0,
'Scale': 0, 'Nullable': 'with Null'
}, self.db.database.datadefs[table_name].colelts)
def open(self):
connection=self.connection
path=os.path
dir=path.join(data_dir,connection)
if not path.isdir(dir):
raise self.database_error, 'invalid database error, ' + connection
if not path.exists(path.join(dir,connection+".gfd")):
db=gadfly.gadfly()
db.startup(connection,dir)
else: db=gadfly.gadfly(connection,dir)
self.db=db
self.opened=DateTime()
def close(self):
self.db=None
del self.opened
def __init__(self,connection):
self.connection=connection
self.open()
def query(self,query_string, max_rows=9999999):
if self.db is None: self.open()
self._register()
c=self.db.cursor()
queries=filter(None, map(strip,split(query_string, '\0')))
if not queries: raise QueryError, 'empty query'
desc=None
result=[]
for qs in queries:
c.execute(qs)
d=c.description
if d is None: continue
if desc is None: desc=d
elif d != desc:
raise QueryError, (
'Multiple incompatible selects in '
'multiple sql-statement query'
)
if not result: result=c.fetchmany(max_rows)
elif len(result) < max_rows:
result=result+c.fetchmany(max_rows-len(result))
if desc is None: return (),()
items=[]
for name, type, width, ds, p, scale, null_ok in desc:
if type=='NUMBER':
if scale==0: type='i'
else: type='n'
elif type=='DATE':
type='d'
else: type='s'
items.append({
'name': name,
'type': type,
'width': width,
'null': null_ok,
})
return items, result
# Gadfly needs the extra checkpoint call.
def _abort(self):
self.db.rollback()
self.db.checkpoint()