23 |
# |
# |
24 |
# DESCRIPTION: |
# DESCRIPTION: |
25 |
# Driver to provide access to data via the Kinterbasdb Interbase/Firebird Python Driver |
# Driver to provide access to data via the Kinterbasdb Interbase/Firebird Python Driver |
26 |
# Requires Kinterbasdb 3.0 (http://kinterbasdb.sourceforge.net/) |
# Requires Kinterbasdb > 3.0 (http://kinterbasdb.sourceforge.net/) |
27 |
# |
# |
28 |
# NOTES: |
# NOTES: |
29 |
# |
# |
59 |
cursor, defaultValues, masterRecordSet) |
cursor, defaultValues, masterRecordSet) |
60 |
self._recordSetClass = Interbase_RecordSet |
self._recordSetClass = Interbase_RecordSet |
61 |
|
|
|
# Override the base _loadNextRecord as the fetchmany() from the cursor |
|
|
# returns an exception instead of an empty sequence. |
|
|
# TODO: will be unneeded when next (>3.0) kinterbasdb release comes out |
|
|
# TODO: in the kinterbasdb CVS the fetchmany() error has been fixed yet (btami) |
|
|
def _loadNextRecord(self): |
|
|
if self._cursor: |
|
|
rs = None |
|
|
|
|
|
try: |
|
|
rsets = self._cursor.fetchmany() |
|
|
except self._dataObject._DatabaseError, err: |
|
|
rsets = None |
|
|
except: |
|
|
rsets = None |
|
|
|
|
|
if rsets and len(rsets): |
|
|
for rs in(rsets): |
|
|
if rs: |
|
|
i = 0 |
|
|
dict = {} |
|
|
for f in (rs): |
|
|
dict[lower(self._fieldNames[i])] = f |
|
|
i += 1 |
|
|
self._cachedRecords.append (self._recordSetClass(parent=self, \ |
|
|
initialData=dict)) |
|
|
else: |
|
|
return 0 |
|
|
return 1 |
|
|
else: |
|
|
return 0 |
|
|
else: |
|
|
return 0 |
|
|
|
|
62 |
|
|
63 |
class Interbase_DataObject(DBSIG_DataObject): |
class Interbase_DataObject(DBSIG_DataObject): |
64 |
def __init__(self): |
def __init__(self): |
65 |
DBSIG_DataObject.__init__(self) |
DBSIG_DataObject.__init__(self) |
66 |
self._DatabaseError = SIG2api.DatabaseError |
self._DatabaseError = SIG2api.DatabaseError |
67 |
self._resultSetClass = Interbase_ResultSet |
self._resultSetClass = Interbase_ResultSet |
68 |
|
self._primaryKeyFields = [] |
69 |
|
|
70 |
def connect(self, connectData={}): |
def connect(self, connectData={}): |
71 |
GDebug.printMesg(1,"Interbase database driver initializing") |
GDebug.printMesg(1,"Interbase database driver initializing") |
72 |
|
|
73 |
|
try: |
74 |
|
charset = connectData['charset'] |
75 |
|
except KeyError: |
76 |
|
charset = "" |
77 |
|
|
78 |
try: |
try: |
79 |
self._dataConnection = SIG2api.connect( \ |
self._dataConnection = SIG2api.connect( \ |
80 |
user=connectData['_username'], \ |
user=connectData['_username'], \ |
81 |
password=connectData['_password'], \ |
password=connectData['_password'], \ |
82 |
|
charset=charset, \ |
83 |
database=connectData['dbname'], \ |
database=connectData['dbname'], \ |
84 |
host=connectData['host']) |
host=connectData['host']) |
85 |
except self._DatabaseError, value: |
except self._DatabaseError, value: |
113 |
list = [] |
list = [] |
114 |
for rs in cursor.fetchall(): |
for rs in cursor.fetchall(): |
115 |
list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]), |
list.append(GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]), |
116 |
'type':'table'}, |
'type':'table', |
117 |
|
'primarykey': self.__getPrimaryKey(rstrip(rs[0]))}, |
118 |
getChildSchema=self.__getFieldSchema)) |
getChildSchema=self.__getFieldSchema)) |
119 |
|
|
120 |
cursor.close() |
cursor.close() |
133 |
rs = cursor.fetchone() |
rs = cursor.fetchone() |
134 |
if rs: |
if rs: |
135 |
schema = GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]), |
schema = GDataObjects.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]), |
136 |
'type':'table'}, |
'type':'table', |
137 |
|
'primarykey': self.__getPrimaryKey(rstrip(rs[0]))}, |
138 |
getChildSchema=self.__getFieldSchema) |
getChildSchema=self.__getFieldSchema) |
139 |
else: |
else: |
140 |
schema = None |
schema = None |
142 |
cursor.close() |
cursor.close() |
143 |
return schema |
return schema |
144 |
|
|
145 |
|
# Return a list of fields (for _buildDeleteStatement and for _buildUpdateStatement) |
146 |
|
def __getPrimaryKey(self, relname): |
147 |
|
statement = "select rdb$relation_name, rdb$field_name, "+\ |
148 |
|
"rdb$constraint_name, rdb$field_position "+\ |
149 |
|
"from rdb$relation_constraints rc, rdb$index_segments ri "+\ |
150 |
|
"where ri.rdb$index_name = rc.rdb$index_name "+\ |
151 |
|
"and rc.rdb$constraint_type = 'PRIMARY KEY' "+\ |
152 |
|
"and rc.rdb$relation_name = '%s' " % (relname)+\ |
153 |
|
"order by ri.rdb$field_position" |
154 |
|
|
155 |
|
cursor = self._dataConnection.cursor() |
156 |
|
cursor.execute(statement) |
157 |
|
|
158 |
|
list = [] |
159 |
|
for rs in cursor.fetchall(): |
160 |
|
list.append(lower(rstrip(rs[1]))) |
161 |
|
|
162 |
|
cursor.close() |
163 |
|
return list |
164 |
|
|
165 |
# Get fields for a table |
# Get fields for a table |
166 |
def __getFieldSchema(self, parent): |
def __getFieldSchema(self, parent): |
167 |
|
|
|
# statement = "select a.rdb$field_name,a.rdb$null_flag,"+\ |
|
|
# "c.rdb$type_name,"+\ |
|
|
# "b.rdb$field_length, "+\ |
|
|
# "b.rdb$field_scale "+\ |
|
|
# "from rdb$relation_fields a, rdb$fields b, rdb$types c "+\ |
|
|
# "where c.rdb$field_name='RDB$FIELD_TYPE' and "+\ |
|
|
# "c.rdb$type=b.rdb$field_type and "+\ |
|
|
# "b.rdb$field_name=a.rdb$field_source and "+\ |
|
|
# "a.rdb$relation_name= '%s'"%(parent.name) |
|
|
|
|
168 |
statement = "select * from %s"%(parent.name) + " where (0=1)" |
statement = "select * from %s"%(parent.name) + " where (0=1)" |
169 |
|
|
170 |
cursor = self._dataConnection.cursor() |
cursor = self._dataConnection.cursor() |
172 |
|
|
173 |
list = [] |
list = [] |
174 |
|
|
|
# for rs in cursor.fetchall(): |
|
|
# nativetype = rstrip(rs[2]) |
|
|
# |
|
|
# attrs={'id': rs[0], 'name': lower(rstrip(rs[0])), |
|
|
# 'type':'field', 'nativetype': nativetype, |
|
|
# 'required': rs[1]==1, 'length': rs[3] } |
|
|
# |
|
|
# if nativetype in ('SHORT','LONG','QUAD','FLOAT','DOUBLE'): |
|
|
# attrs['datatype']='number' |
|
|
# attrs['precision'] = rs[4] |
|
|
# elif nativetype in ('DATE','TIME','TIMESTAMP'): |
|
|
# attrs['datatype']='date' |
|
|
# else: |
|
|
# attrs['datatype']='text' |
|
|
|
|
175 |
for d in cursor.description: |
for d in cursor.description: |
176 |
nativetype = lower(d[SIG2api.DESCRIPTION_TYPE_CODE].__name__) |
try: |
177 |
|
nativetype = lower(d[SIG2api.DESCRIPTION_TYPE_CODE].__name__) |
178 |
|
except AttributeError: |
179 |
|
nativetype='unknown' |
180 |
|
|
181 |
attrs={'id':d[SIG2api.DESCRIPTION_NAME], |
attrs={'id':d[SIG2api.DESCRIPTION_NAME], |
182 |
'name':lower(d[SIG2api.DESCRIPTION_NAME]), |
'name':lower(d[SIG2api.DESCRIPTION_NAME]), |