1
# GNU Enterprise Common - Base DB Driver - Connection
3
# Copyright 2001-2005 Free Software Foundation
5
# This file is part of GNU Enterprise
7
# GNU Enterprise is free software; you can redistribute it
8
# and/or modify it under the terms of the GNU General Public
9
# License as published by the Free Software Foundation; either
10
# version 2, or (at your option) any later version.
12
# GNU Enterprise is distributed in the hope that it will be
13
# useful, but WITHOUT ANY WARRANTY; without even the implied
14
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15
# PURPOSE. See the GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public
18
# License along with program; see the file COPYING. If not,
19
# write to the Free Software Foundation, Inc., 59 Temple Place
20
# - Suite 330, Boston, MA 02111-1307, USA.
22
# $Id: Connection.py 7057 2005-02-23 16:53:58Z johannes $
27
__all__ = ['Connection']
31
# +-- GConnections initializes
32
# +-- GParser initializes:
33
# +-- GDataSource loaded
34
# +-- GDataSources Intialized
35
# +-- GConnection.getDataObject()
39
def __init__(self, connections, name, parameters):
40
self.manager = connections
41
self.parameters = parameters
44
# Text encoding used by the database.
45
# (Not all databases support this concept)
47
self._encoding = parameters['encoding']
50
self._encoding = gConfig('textEncoding')
52
# TODO: Is this a safe default?
53
self._encoding = 'iso8859-1'
56
# Commit changes to the database
60
# Rollback changes to the database
64
# Close the connection to the database backend
67
# Make sure to release the reference to the connection manager as well as
68
# the introspector's instance (if available). This makes garbage collection
71
if hasattr (self, 'introspector'):
72
self.introspector = None
75
def connect(self, connectData):
79
# ---------------------------------------------------------------------------
80
# Create a new instance of the associated schema creator
81
# ---------------------------------------------------------------------------
83
def getSchemaCreator (self):
85
This function creates a new instance of the schema creator associated with
86
this driver or None if no creator is available.
89
if hasattr (self, 'defaultCreator') and self.defaultCreator:
90
return self.defaultCreator (self)
95
# ---------------------------------------------------------------------------
96
# update the schema definition
97
# ---------------------------------------------------------------------------
99
def updateSchema (self, definition, codeOnly = False):
101
This function modifies the database schema according to the given
102
definition, which is a dictionary of table defininitions (@see:
103
Schema.Creation.Creation), where the tablenames are the keys.
105
@param definition: sequence of table definitions
106
@param codeOnly: if TRUE, only the code will be generated to modify the
107
schema, no actions take place.
108
@return: a tuple of three sequences (prologue, body, epilogue) holding the
109
code to perform all schema modifications needed. These sequences should
110
be executed in this order to successfully create the schema.
113
result = ([], [], [])
115
schemaCreator = self.getSchemaCreator ()
117
if schemaCreator is None:
121
workingSet = copy.copy (definition)
124
# before any actions are performed, validate the given definitions
125
for table in definition:
126
schemaCreator.validate (table)
128
# in a first run we remove all constraint definitions from the tables, so
129
# we can add or alter all tables without having troubles with order of
131
for table in workingSet:
132
# Do we have already a table with that name?
133
res = self.introspector.find (name = table ['name'])
136
method = schemaCreator.modifyTable
137
# Please note: we keep existingFields sequence in all lowercase
138
existingFields = [f.name.lower () for f in res [0].fields ()]
140
# keep only new fields
142
for field in table ['fields']:
143
if not field ['name'].lower () in existingFields:
146
table ['fields'] = keep
148
# on updates of a table we cannot use a primary key
149
if table.has_key ('primarykey'):
150
del table ['primarykey']
152
# keep modified or new indices only
153
if table.has_key ('indices'):
156
# if driver supports index-introspection we'll use it
157
if hasattr (res [0], 'indices'):
158
for index in table ['indices']:
160
for (name, value) in res [0].indices.items ():
161
if name.lower () == index ['name'].lower ():
167
old = [f.lower () for f in oldIndex ['fields']]
168
new = [f.lower () for f in index ['fields']]
170
if oldIndex ['unique'] != index ['unique'] or old != new:
172
# make sure the backend has a possibility to remove the old
173
# index before changing it
174
if not table.has_key ('old_indices'):
175
table ['old_indices'] = []
176
table ['old_indices'].append (index ['name'])
180
# if no index-introspection available we only keep an index, if it
182
for index in table ['indices']:
183
for field in index ['fields']:
184
if not field.lower () in existingFields:
185
# make sure the backend has a possibility to remove the old
186
# index before changing it
187
if not table.has_key ('old_indices'):
188
table ['old_indices'] = []
189
table ['old_indices'].append (index ['name'])
194
table ['indices'] = keep
196
# we create a constraint on a table update only if it contains new
198
if table.has_key ('constraints'):
201
for constraint in table ['constraints']:
202
for field in constraint ['fields']:
203
if not field.lower () in existingFields:
204
keep.append (constraint)
207
table ['constraints'] = keep
210
method = schemaCreator.createTable
212
if table.has_key ('constraints'):
213
constraintSet [table ['name']] = {'name': table ['name'],
214
'constraints': table ['constraints']}
215
del table ['constraints']
217
# before we execute the planned action, have a look if there's still
219
perform = table.has_key ('fields') and len (table ['fields'])
220
perform = perform or table.has_key ('primarykey')
221
perform = perform or (table.has_key ('indices') and \
222
len (table ['indices']))
225
schemaCreator.mergeTuple (result, method (table, codeOnly))
227
# on the second run we process all constraints
228
for table in constraintSet.values ():
229
schemaCreator.mergeTuple (result,
230
schemaCreator.createTable (table, codeOnly))
234
schemaCreator.close ()