1 |
|
# |
2 |
|
# This file is part of GNU Enterprise. |
3 |
|
# |
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. |
8 |
|
# |
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. |
13 |
|
# |
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. |
18 |
|
# |
19 |
|
# Copyright 2001-2003 Free Software Foundation |
20 |
|
# |
21 |
|
# FILE: |
22 |
|
# dbf/DBdriver.py |
23 |
|
# |
24 |
|
# DESCRIPTION: |
25 |
|
# Virtual database driver for loading data from a DBF file |
26 |
|
# |
27 |
|
# NOTES: |
28 |
|
# Used whenever a data has to be imported from dbase III+ |
29 |
|
# |
30 |
|
|
31 |
|
__all__ = ['RecordSet'] |
32 |
|
|
33 |
|
from gnue.common.apps import GDebug |
34 |
|
import string |
35 |
|
from gnue.common.datasources.GDataObjects import * |
36 |
|
from gnue.common.drivers.special.static.Driver import * |
37 |
|
import dbf |
38 |
|
|
39 |
|
|
40 |
|
########################################################### |
41 |
|
# |
42 |
|
# This is an static data driver for connectionless clients |
43 |
|
# |
44 |
|
########################################################### |
45 |
|
class DBF_DataObject (STATIC_DataObject): |
46 |
|
|
47 |
|
def __init__(self): |
48 |
|
DataObject.__init__(self) |
49 |
|
self.triggerExtensions = TriggerExtensions(self) |
50 |
|
self._DatabaseError = Error |
51 |
|
|
52 |
|
def _createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, sql=""): |
53 |
|
return DBF_ResultSet(self, masterRecordSet=masterRecordSet) |
54 |
|
|
55 |
|
|
56 |
|
# We don't do connections (we are connectionless) |
57 |
|
def connect(self, connectData={}): |
58 |
|
try: |
59 |
|
GDebug.printMesg(3,'Open file: %s' % (connectData['directory']+connectData['dbname'])) |
60 |
|
self._dataConnection = dbf.dbf(connectData['directory']+\ |
61 |
|
connectData['dbname']) |
62 |
|
except IOError: |
63 |
|
tmsg = _('DBF file not found.') |
64 |
|
raise self._DatabaseError, tmsg |
65 |
|
except TypeError: |
66 |
|
tmsg = _('Wrong file format.') |
67 |
|
raise self._DatabaseError, tmsg |
68 |
|
|
69 |
|
# build field list |
70 |
|
self._fieldReferences=[] |
71 |
|
for f in self._dataConnection.fields: |
72 |
|
self._fieldReferences.append(string.lower(f[0])) |
73 |
|
|
74 |
|
self._postConnect() |
75 |
|
|
76 |
|
# |
77 |
|
# Schema (metadata) functions |
78 |
|
# |
79 |
|
|
80 |
|
# Return a list of the types of Schema objects this driver provides |
81 |
|
def getSchemaTypes(self): |
82 |
|
return [('table',_('Tables'),1)] |
83 |
|
|
84 |
|
# Return a list of Schema objects |
85 |
|
def getSchemaList(self, type=None): |
86 |
|
tablename=self._dataConnection.fname |
87 |
|
if tablename[-4:]=='.dbf': |
88 |
|
tablename=tablename[:-4] |
89 |
|
|
90 |
|
list = [Schema(attrs={'id':tablename,\ |
91 |
|
'name':tablename, \ |
92 |
|
'type':1},\ |
93 |
|
getChildSchema=self.__getFieldSchema)] |
94 |
|
return list |
95 |
|
|
96 |
|
|
97 |
|
# Find a schema object with specified name |
98 |
|
def getSchemaByName(self, name, type=None): |
99 |
|
tablename=self._dataConnection.fname |
100 |
|
if tablename[-4:]=='.dbf': |
101 |
|
tablename=tablename[:-4] |
102 |
|
|
103 |
|
if name==tablename: |
104 |
|
return self.getSchemaList() |
105 |
|
else: |
106 |
|
return None |
107 |
|
|
108 |
|
# Get fields for a table |
109 |
|
def __getFieldSchema(self, parent): |
110 |
|
|
111 |
|
list = [] |
112 |
|
for field in self._dataConnection.fields: |
113 |
|
|
114 |
|
fname=string.lower(field[0]) |
115 |
|
|
116 |
|
attrs={'id': "%s.%s" % (parent.id,fname), 'name': fname, |
117 |
|
'type':'field', 'nativetype': field[1], |
118 |
|
'required': 0} |
119 |
|
if field[1] == 'C': |
120 |
|
attrs['datatype']='text' |
121 |
|
attrs['length']='%s' % field[2] |
122 |
|
elif field[1] == 'N': |
123 |
|
attrs['datatype']='number' |
124 |
|
elif field[1] == 'D': |
125 |
|
attrs['datatype']='date' |
126 |
|
elif field[1] == 'L': |
127 |
|
attrs['datatype']='boolean' |
128 |
|
else: |
129 |
|
GDebug.printMesg(1,'WARNING: dbf native type error: %s' % field[1]) |
130 |
|
|
131 |
|
list.append(Schema(attrs=attrs)) |
132 |
|
|
133 |
|
return list |
134 |
|
|
135 |
|
|
136 |
|
|
137 |
|
|
138 |
|
########################################################### |
139 |
|
# |
140 |
|
# |
141 |
|
# |
142 |
|
########################################################### |
143 |
|
class DBF_ResultSet(STATIC_ResultSet): |
144 |
|
|
145 |
|
def __init__(self, dataObject, cursor=None, defaultValues={}, masterRecordSet=None): |
146 |
|
ResultSet.__init__(self, dataObject, \ |
147 |
|
cursor, defaultValues, masterRecordSet) |
148 |
|
|
149 |
|
self._recordSetClass = STATIC_RecordSet |
150 |
|
|
151 |
|
# Returns 1=DataObject has uncommitted changes |
152 |
|
def isPending(self): |
153 |
|
return 0 # Static DataObjects cannot have pending changes :) |
154 |
|
|
155 |
|
# Post changes to the database |
156 |
|
def post(self): |
157 |
|
# Leave this here in case (for some bizarro reason) |
158 |
|
# a bound dataobject uses us as a master |
159 |
|
for record in (self._cachedRecords): |
160 |
|
record.post() |
161 |
|
|
162 |
|
# Load cacheCount number of new records |
163 |
|
def _loadNextRecord(self): |
164 |
|
if hasattr(self,"_alldataloaded"): |
165 |
|
return 0 |
166 |
|
|
167 |
|
# Load static data |
168 |
|
for row in self._dataObject._dataConnection: |
169 |
|
dict = {} |
170 |
|
c=0 |
171 |
|
for f in self._dataObject._dataConnection.fields: |
172 |
|
dict[string.lower(f[0])] = row[c] |
173 |
|
c+=1 |
174 |
|
|
175 |
|
record=self._recordSetClass(parent=self,initialData=dict) |
176 |
|
|
177 |
|
self._cachedRecords.append (record) |
178 |
|
|
179 |
|
self._recordCount=self._recordCount+1 |
180 |
|
|
181 |
|
self._alldataloaded = 1 |
182 |
|
|
183 |
|
return 1 |
184 |
|
|
185 |
|
|
186 |
|
|
187 |
|
###################################### |
188 |
|
# |
189 |
|
# The following hashes describe |
190 |
|
# this driver's characteristings. |
191 |
|
# |
192 |
|
###################################### |
193 |
|
|
194 |
|
# |
195 |
|
# All datasouce "types" and corresponding DataObject class |
196 |
|
# |
197 |
|
supportedDataObjects = { |
198 |
|
'static': DBF_DataObject, |
199 |
|
'object': DBF_DataObject |
200 |
|
} |
201 |
|
|
202 |
|
|