KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > entity > jdbc > DatabaseUtil


1 /*
2  * $Id: DatabaseUtil.java 6984 2006-03-11 16:15:13Z jonesde $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */

24 package org.ofbiz.entity.jdbc;
25
26 import java.io.Serializable JavaDoc;
27 import java.sql.Connection JavaDoc;
28 import java.sql.DatabaseMetaData JavaDoc;
29 import java.sql.ResultSet JavaDoc;
30 import java.sql.SQLException JavaDoc;
31 import java.sql.Statement JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Collection JavaDoc;
34 import java.util.Collections JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.Set JavaDoc;
39 import java.util.TreeSet JavaDoc;
40
41 import javolution.util.FastList;
42 import javolution.util.FastMap;
43 import org.w3c.dom.Document JavaDoc;
44 import org.w3c.dom.Element JavaDoc;
45
46 import org.ofbiz.base.util.Debug;
47 import org.ofbiz.base.util.UtilTimer;
48 import org.ofbiz.base.util.UtilValidate;
49 import org.ofbiz.base.util.UtilXml;
50 import org.ofbiz.entity.GenericEntityException;
51 import org.ofbiz.entity.config.DatasourceInfo;
52 import org.ofbiz.entity.config.EntityConfigUtil;
53 import org.ofbiz.entity.model.ModelEntity;
54 import org.ofbiz.entity.model.ModelField;
55 import org.ofbiz.entity.model.ModelFieldType;
56 import org.ofbiz.entity.model.ModelFieldTypeReader;
57 import org.ofbiz.entity.model.ModelIndex;
58 import org.ofbiz.entity.model.ModelKeyMap;
59 import org.ofbiz.entity.model.ModelRelation;
60 import org.ofbiz.entity.model.ModelViewEntity;
61
62 /**
63  * Utilities for Entity Database Maintenance
64  *
65  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
66  * @version $Rev: 6984 $
67  * @since 2.0
68  */

69 public class DatabaseUtil {
70
71     public static final String JavaDoc module = DatabaseUtil.class.getName();
72
73     // OFBiz Connections
74
protected ModelFieldTypeReader modelFieldTypeReader = null;
75     protected DatasourceInfo datasourceInfo = null;
76     protected String JavaDoc helperName = null;
77
78     // Legacy Connections
79
protected String JavaDoc connectionUrl = null;
80     protected String JavaDoc driverName = null;
81     protected String JavaDoc userName = null;
82     protected String JavaDoc password = null;
83
84     boolean isLegacy = false;
85
86     // OFBiz DatabaseUtil
87
public DatabaseUtil(String JavaDoc helperName) {
88         this.helperName = helperName;
89         this.modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName);
90         this.datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperName);
91     }
92
93     // Legacy DatabaseUtil
94
public DatabaseUtil(String JavaDoc driverName, String JavaDoc connectionUrl, String JavaDoc userName, String JavaDoc password) {
95         this.driverName = driverName;
96         this.connectionUrl = connectionUrl;
97         this.userName = userName;
98         this.password = password;
99         this.isLegacy = true;
100     }
101
102     protected Connection JavaDoc getConnection() throws SQLException JavaDoc, GenericEntityException {
103         Connection JavaDoc connection = null;
104         if (!isLegacy) {
105             connection = ConnectionFactory.getConnection(helperName);
106         } else {
107             connection = ConnectionFactory.getConnection(driverName, connectionUrl, null, userName, password);
108         }
109
110         if (connection == null) {
111             if (!isLegacy) {
112                 throw new GenericEntityException("No connection available for helper named [" + helperName + "]");
113             } else {
114                 throw new GenericEntityException("No connection avaialble for URL [" + connectionUrl + "]");
115             }
116         }
117         connection.setAutoCommit(true);
118         return connection;
119     }
120
121     public DatasourceInfo getDatasourceInfo() {
122         return this.datasourceInfo;
123     }
124
125     /* ====================================================================== */
126
127     /* ====================================================================== */
128
129     public void checkDb(Map JavaDoc modelEntities, List JavaDoc messages, boolean addMissing) {
130         checkDb(modelEntities, null, messages, datasourceInfo.checkPrimaryKeysOnStart, (datasourceInfo.useFks && datasourceInfo.checkForeignKeysOnStart), (datasourceInfo.useFkIndices && datasourceInfo.checkFkIndicesOnStart), addMissing);
131     }
132
133     public void checkDb(Map JavaDoc modelEntities, List JavaDoc colWrongSize, List JavaDoc messages, boolean checkPks, boolean checkFks, boolean checkFkIdx, boolean addMissing) {
134         if (isLegacy) {
135             throw new RuntimeException JavaDoc("Cannot run checkDb on a legacy database connection; configure a database helper (entityengine.xml)");
136         }
137         UtilTimer timer = new UtilTimer();
138         timer.timerString("Start - Before Get Database Meta Data");
139
140         // get ALL tables from this database
141
TreeSet JavaDoc tableNames = this.getTableNames(messages);
142         TreeSet JavaDoc fkTableNames = tableNames == null ? null : new TreeSet JavaDoc(tableNames);
143         TreeSet JavaDoc indexTableNames = tableNames == null ? null : new TreeSet JavaDoc(tableNames);
144
145         if (tableNames == null) {
146             String JavaDoc message = "Could not get table name information from the database, aborting.";
147             if (messages != null) messages.add(message);
148             Debug.logError(message, module);
149             return;
150         }
151         timer.timerString("After Get All Table Names");
152
153         // get ALL column info, put into hashmap by table name
154
Map JavaDoc colInfo = this.getColumnInfo(tableNames, checkPks, messages);
155         if (colInfo == null) {
156             String JavaDoc message = "Could not get column information from the database, aborting.";
157             if (messages != null) messages.add(message);
158             Debug.logError(message, module);
159             return;
160         }
161         timer.timerString("After Get All Column Info");
162
163         // -make sure all entities have a corresponding table
164
// -list all tables that do not have a corresponding entity
165
// -display message if number of table columns does not match number of entity fields
166
// -list all columns that do not have a corresponding field
167
// -make sure each corresponding column is of the correct type
168
// -list all fields that do not have a corresponding column
169

170         timer.timerString("Before Individual Table/Column Check");
171
172         ArrayList JavaDoc modelEntityList = new ArrayList JavaDoc(modelEntities.values());
173         // sort using compareTo method on ModelEntity
174
Collections.sort(modelEntityList);
175         Iterator JavaDoc modelEntityIter = modelEntityList.iterator();
176         int curEnt = 0;
177         int totalEnt = modelEntityList.size();
178         List JavaDoc entitiesAdded = FastList.newInstance();
179         while (modelEntityIter.hasNext()) {
180             curEnt++;
181             ModelEntity entity = (ModelEntity) modelEntityIter.next();
182
183             // if this is a view entity, do not check it...
184
if (entity instanceof ModelViewEntity) {
185                 String JavaDoc entMessage = "(" + timer.timeSinceLast() + "ms) NOT Checking #" + curEnt + "/" + totalEnt + " View Entity " + entity.getEntityName();
186                 Debug.logVerbose(entMessage, module);
187                 if (messages != null) messages.add(entMessage);
188                 continue;
189             }
190
191             String JavaDoc entMessage = "(" + timer.timeSinceLast() + "ms) Checking #" + curEnt + "/" + totalEnt +
192                 " Entity " + entity.getEntityName() + " with table " + entity.getTableName(datasourceInfo);
193
194             Debug.logVerbose(entMessage, module);
195             if (messages != null) messages.add(entMessage);
196
197             // -make sure all entities have a corresponding table
198
if (tableNames.contains(entity.getTableName(datasourceInfo))) {
199                 tableNames.remove(entity.getTableName(datasourceInfo));
200
201                 if (colInfo != null) {
202                     Map JavaDoc fieldColNames = FastMap.newInstance();
203                     Iterator JavaDoc fieldIter = entity.getFieldsIterator();
204                     while (fieldIter.hasNext()) {
205                         ModelField field = (ModelField) fieldIter.next();
206                         fieldColNames.put(field.getColName(), field);
207                     }
208
209                     Map JavaDoc colMap = (Map JavaDoc) colInfo.get(entity.getTableName(datasourceInfo));
210                     if (colMap != null) {
211                         Iterator JavaDoc colEntryIter = colMap.entrySet().iterator();
212                         while (colEntryIter.hasNext()) {
213                             Map.Entry JavaDoc colEntry = (Map.Entry JavaDoc) colEntryIter.next();
214                             ColumnCheckInfo ccInfo = (ColumnCheckInfo) colEntry.getValue();
215
216                             // -list all columns that do not have a corresponding field
217
if (fieldColNames.containsKey(ccInfo.columnName)) {
218                                 ModelField field = null;
219
220                                 field = (ModelField) fieldColNames.remove(ccInfo.columnName);
221                                 ModelFieldType modelFieldType = modelFieldTypeReader.getModelFieldType(field.getType());
222
223                                 if (modelFieldType != null) {
224                                     // make sure each corresponding column is of the correct type
225
String JavaDoc fullTypeStr = modelFieldType.getSqlType();
226                                     String JavaDoc typeName;
227                                     int columnSize = -1;
228                                     int decimalDigits = -1;
229
230                                     int openParen = fullTypeStr.indexOf('(');
231                                     int closeParen = fullTypeStr.indexOf(')');
232                                     int comma = fullTypeStr.indexOf(',');
233
234                                     if (openParen > 0 && closeParen > 0 && closeParen > openParen) {
235                                         typeName = fullTypeStr.substring(0, openParen);
236                                         if (comma > 0 && comma > openParen && comma < closeParen) {
237                                             String JavaDoc csStr = fullTypeStr.substring(openParen + 1, comma);
238                                             try {
239                                                 columnSize = Integer.parseInt(csStr);
240                                             } catch (NumberFormatException JavaDoc e) {
241                                                 Debug.logError(e, module);
242                                             }
243
244                                             String JavaDoc ddStr = fullTypeStr.substring(comma + 1, closeParen);
245                                             try {
246                                                 decimalDigits = Integer.parseInt(ddStr);
247                                             } catch (NumberFormatException JavaDoc e) {
248                                                 Debug.logError(e, module);
249                                             }
250                                         } else {
251                                             String JavaDoc csStr = fullTypeStr.substring(openParen + 1, closeParen);
252                                             try {
253                                                 columnSize = Integer.parseInt(csStr);
254                                             } catch (NumberFormatException JavaDoc e) {
255                                                 Debug.logError(e, module);
256                                             }
257                                         }
258                                     } else {
259                                         typeName = fullTypeStr;
260                                     }
261
262                                     // override the default typeName with the sqlTypeAlias if it is specified
263
if (UtilValidate.isNotEmpty(modelFieldType.getSqlTypeAlias())) {
264                                         typeName = modelFieldType.getSqlTypeAlias();
265                                     }
266
267                                     // NOTE: this may need a toUpperCase in some cases, keep an eye on it, okay just compare with ignore case
268
if (!ccInfo.typeName.equalsIgnoreCase(typeName)) {
269                                         String JavaDoc message = "WARNING: Column [" + ccInfo.columnName + "] of table [" + entity.getTableName(datasourceInfo) + "] of entity [" +
270                                             entity.getEntityName() + "] is of type [" + ccInfo.typeName + "] in the database, but is defined as type [" +
271                                             typeName + "] in the entity definition.";
272                                         Debug.logError(message, module);
273                                         if (messages != null) messages.add(message);
274                                     }
275                                     if (columnSize != -1 && ccInfo.columnSize != -1 && columnSize != ccInfo.columnSize && (columnSize * 3) != ccInfo.columnSize) {
276                                         String JavaDoc message = "WARNING: Column [" + ccInfo.columnName + "] of table [" + entity.getTableName(datasourceInfo) + "] of entity [" +
277                                             entity.getEntityName() + "] has a column size of [" + ccInfo.columnSize +
278                                             "] in the database, but is defined to have a column size of [" + columnSize + "] in the entity definition.";
279                                         Debug.logWarning(message, module);
280                                         if (messages != null) messages.add(message);
281                                         if (columnSize > ccInfo.columnSize && colWrongSize != null) {
282                                             // add item to list of wrong sized columns; only if the entity is larger
283
colWrongSize.add(entity.getEntityName() + "." + field.getName());
284                                         }
285                                     }
286                                     if (decimalDigits != -1 && decimalDigits != ccInfo.decimalDigits) {
287                                         String JavaDoc message = "WARNING: Column [" + ccInfo.columnName + "] of table [" + entity.getTableName(datasourceInfo) + "] of entity [" +
288                                             entity.getEntityName() + "] has a decimalDigits of [" + ccInfo.decimalDigits +
289                                             "] in the database, but is defined to have a decimalDigits of [" + decimalDigits + "] in the entity definition.";
290                                         Debug.logWarning(message, module);
291                                         if (messages != null) messages.add(message);
292                                     }
293
294                                     // do primary key matching check
295
if (checkPks && ccInfo.isPk && !field.getIsPk()) {
296                                         String JavaDoc message = "WARNING: Column [" + ccInfo.columnName + "] of table [" + entity.getTableName(datasourceInfo) + "] of entity [" +
297                                             entity.getEntityName() + "] IS a primary key in the database, but IS NOT a primary key in the entity definition. The primary key for this table needs to be re-created or modified so that this column is NOT party of the primary key.";
298                                         Debug.logError(message, module);
299                                         if (messages != null) messages.add(message);
300                                     }
301                                     if (checkPks && !ccInfo.isPk && field.getIsPk()) {
302                                         String JavaDoc message = "WARNING: Column [" + ccInfo.columnName + "] of table [" + entity.getTableName(datasourceInfo) + "] of entity [" +
303                                             entity.getEntityName() + "] IS NOT a primary key in the database, but IS a primary key in the entity definition. The primary key for this table needs to be re-created or modified to add this column to the primary key. Note that data may need to be added first as a primary key column cannot have an null values.";
304                                         Debug.logError(message, module);
305                                         if (messages != null) messages.add(message);
306                                     }
307                                 } else {
308                                     String JavaDoc message = "Column [" + ccInfo.columnName + "] of table [" + entity.getTableName(datasourceInfo) + "] of entity [" + entity.getEntityName() +
309                                         "] has a field type name of [" + field.getType() + "] which is not found in the field type definitions";
310                                     Debug.logError(message, module);
311                                     if (messages != null) messages.add(message);
312                                 }
313                             } else {
314                                 String JavaDoc message = "Column [" + ccInfo.columnName + "] of table [" + entity.getTableName(datasourceInfo) + "] of entity [" + entity.getEntityName() + "] exists in the database but has no corresponding field" + ((checkPks && ccInfo.isPk) ? " (and it is a PRIMARY KEY COLUMN)" : "");
315                                 Debug.logWarning(message, module);
316                                 if (messages != null) messages.add(message);
317                             }
318                         }
319
320                         // -display message if number of table columns does not match number of entity fields
321
if (colMap.size() != entity.getFieldsSize()) {
322                             String JavaDoc message = "Entity [" + entity.getEntityName() + "] has " + entity.getFieldsSize() + " fields but table [" + entity.getTableName(datasourceInfo) + "] has " + colMap.size() + " columns.";
323                             Debug.logWarning(message, module);
324                             if (messages != null) messages.add(message);
325                         }
326                     }
327
328                     // -list all fields that do not have a corresponding column
329
Iterator JavaDoc fcnIter = fieldColNames.keySet().iterator();
330                     while (fcnIter.hasNext()) {
331                         String JavaDoc colName = (String JavaDoc) fcnIter.next();
332                         ModelField field = (ModelField) fieldColNames.get(colName);
333                         String JavaDoc message = "Field [" + field.getName() + "] of entity [" + entity.getEntityName() + "] is missing its corresponding column [" + field.getColName() + "]" + (field.getIsPk() ? " (and it is a PRIMARY KEY FIELD)" : "");
334
335                         Debug.logWarning(message, module);
336                         if (messages != null) messages.add(message);
337
338                         if (addMissing) {
339                             // add the column
340
String JavaDoc errMsg = addColumn(entity, field);
341
342                             if (errMsg != null && errMsg.length() > 0) {
343                                 message = "Could not add column [" + field.getColName() + "] to table [" + entity.getTableName(datasourceInfo) + "]: " + errMsg;
344                                 Debug.logError(message, module);
345                                 if (messages != null) messages.add(message);
346                             } else {
347                                 message = "Added column [" + field.getColName() + "] to table [" + entity.getTableName(datasourceInfo) + "]" + (field.getIsPk() ? " (NOTE: this is a PRIMARY KEY FIELD, but the primary key was not updated automatically (not considered a safe operation), be sure to fill in any needed data and re-create the primary key)" : "");
348                                 Debug.logImportant(message, module);
349                                 if (messages != null) messages.add(message);
350                             }
351                         }
352                     }
353                 }
354             } else {
355                 String JavaDoc message = "Entity [" + entity.getEntityName() + "] has no table in the database";
356                 Debug.logWarning(message, module);
357                 if (messages != null) messages.add(message);
358
359                 if (addMissing) {
360                     // create the table
361
String JavaDoc errMsg = createTable(entity, modelEntities, false);
362                     if (errMsg != null && errMsg.length() > 0) {
363                         message = "Could not create table [" + entity.getTableName(datasourceInfo) + "]: " + errMsg;
364                         Debug.logError(message, module);
365                         if (messages != null) messages.add(message);
366                     } else {
367                         entitiesAdded.add(entity);
368                         message = "Created table [" + entity.getTableName(datasourceInfo) + "]";
369                         Debug.logImportant(message, module);
370                         if (messages != null) messages.add(message);
371                     }
372                 }
373             }
374         }
375
376         timer.timerString("After Individual Table/Column Check");
377
378         // -list all tables that do not have a corresponding entity
379
Iterator JavaDoc tableNamesIter = tableNames.iterator();
380         while (tableNamesIter != null && tableNamesIter.hasNext()) {
381             String JavaDoc tableName = (String JavaDoc) tableNamesIter.next();
382             String JavaDoc message = "Table named [" + tableName + "] exists in the database but has no corresponding entity";
383             Debug.logWarning(message, module);
384             if (messages != null) messages.add(message);
385         }
386
387         // for each newly added table, add fk indices
388
if (datasourceInfo.useFkIndices) {
389             int totalFkIndices = 0;
390             Iterator JavaDoc eaIter = entitiesAdded.iterator();
391             while (eaIter.hasNext()) {
392                 ModelEntity curEntity = (ModelEntity) eaIter.next();
393                 if (curEntity.getRelationsOneSize() > 0) {
394                     totalFkIndices += this.createForeignKeyIndices(curEntity, datasourceInfo.constraintNameClipLength, messages);
395                 }
396             }
397             if (totalFkIndices > 0) Debug.logImportant("==== TOTAL Foreign Key Indices Created: " + totalFkIndices, module);
398         }
399
400         // for each newly added table, add fks
401
if (datasourceInfo.useFks) {
402             int totalFks = 0;
403             Iterator JavaDoc eaIter = entitiesAdded.iterator();
404             while (eaIter.hasNext()) {
405                 ModelEntity curEntity = (ModelEntity) eaIter.next();
406                 totalFks += this.createForeignKeys(curEntity, modelEntities, datasourceInfo.constraintNameClipLength, datasourceInfo.fkStyle, datasourceInfo.useFkInitiallyDeferred, messages);
407             }
408             if (totalFks > 0) Debug.logImportant("==== TOTAL Foreign Keys Created: " + totalFks, module);
409         }
410
411         // for each newly added table, add declared indexes
412
if (datasourceInfo.useIndices) {
413             int totalDis = 0;
414             Iterator JavaDoc eaIter = entitiesAdded.iterator();
415             while (eaIter.hasNext()) {
416                 ModelEntity curEntity = (ModelEntity) eaIter.next();
417                 if (curEntity.getIndexesSize() > 0) {
418                     totalDis += this.createDeclaredIndices(curEntity, messages);
419                 }
420             }
421             if (totalDis > 0) Debug.logImportant("==== TOTAL Declared Indices Created: " + totalDis, module);
422         }
423
424         // make sure each one-relation has an FK
425
if (checkFks) {
426         //if (!justColumns && datasourceInfo.useFks && datasourceInfo.checkForeignKeysOnStart) {
427
// NOTE: This ISN'T working for Postgres or MySQL, who knows about others, may be from JDBC driver bugs...
428
int numFksCreated = 0;
429             // TODO: check each key-map to make sure it exists in the FK, if any differences warn and then remove FK and recreate it
430

431             // get ALL column info, put into hashmap by table name
432
Map JavaDoc refTableInfoMap = this.getReferenceInfo(fkTableNames, messages);
433
434             // Debug.logVerbose("Ref Info Map: " + refTableInfoMap, module);
435

436             if (refTableInfoMap == null) {
437                 // uh oh, something happened while getting info...
438
if (Debug.verboseOn()) Debug.logVerbose("Ref Table Info Map is null", module);
439             } else {
440                 Iterator JavaDoc refModelEntityIter = modelEntityList.iterator();
441                 while (refModelEntityIter.hasNext()) {
442                     ModelEntity entity = (ModelEntity) refModelEntityIter.next();
443                     String JavaDoc entityName = entity.getEntityName();
444                     // if this is a view entity, do not check it...
445
if (entity instanceof ModelViewEntity) {
446                         String JavaDoc entMessage = "NOT Checking View Entity " + entity.getEntityName();
447                         Debug.logVerbose(entMessage, module);
448                         if (messages != null) {
449                             messages.add(entMessage);
450                         }
451                         continue;
452                     }
453
454                     // get existing FK map for this table
455
Map JavaDoc rcInfoMap = (Map JavaDoc) refTableInfoMap.get(entity.getTableName(datasourceInfo));
456                     // Debug.logVerbose("Got ref info for table " + entity.getTableName(datasourceInfo) + ": " + rcInfoMap, module);
457

458                     // go through each relation to see if an FK already exists
459
Iterator JavaDoc relations = entity.getRelationsIterator();
460                     boolean createdConstraints = false;
461                     while (relations.hasNext()) {
462                         ModelRelation modelRelation = (ModelRelation) relations.next();
463                         if (!"one".equals(modelRelation.getType())) {
464                             continue;
465                         }
466
467                         ModelEntity relModelEntity = (ModelEntity) modelEntities.get(modelRelation.getRelEntityName());
468                         if (relModelEntity == null) {
469                             Debug.logError("No such relation: " + entity.getEntityName() + " -> " + modelRelation.getRelEntityName(), module);
470                             continue;
471                         }
472                         String JavaDoc relConstraintName = makeFkConstraintName(modelRelation, datasourceInfo.constraintNameClipLength);
473                         ReferenceCheckInfo rcInfo = null;
474
475                         if (rcInfoMap != null) {
476                             rcInfo = (ReferenceCheckInfo) rcInfoMap.get(relConstraintName);
477                         }
478
479                         if (rcInfo != null) {
480                             rcInfoMap.remove(relConstraintName);
481                         } else {
482                             // if not, create one
483
String JavaDoc noFkMessage = "No Foreign Key Constraint [" + relConstraintName + "] found for entity [" + entityName + "]";
484                             if (messages != null) messages.add(noFkMessage);
485                             if (Debug.infoOn()) Debug.logInfo(noFkMessage, module);
486
487                             if (addMissing) {
488                                 String JavaDoc errMsg = createForeignKey(entity, modelRelation, relModelEntity, datasourceInfo.constraintNameClipLength, datasourceInfo.fkStyle, datasourceInfo.useFkInitiallyDeferred);
489                                 if (errMsg != null && errMsg.length() > 0) {
490                                     String JavaDoc message = "Could not create foreign key " + relConstraintName + " for entity [" + entity.getEntityName() + "]: " + errMsg;
491                                     Debug.logError(message, module);
492                                     if (messages != null) messages.add(message);
493                                 } else {
494                                     String JavaDoc message = "Created foreign key " + relConstraintName + " for entity [" + entity.getEntityName() + "]";
495                                     Debug.logVerbose(message, module);
496                                     if (messages != null) messages.add(message);
497                                     createdConstraints = true;
498                                     numFksCreated++;
499                                 }
500                             }
501                         }
502                     }
503                     if (createdConstraints) {
504                         String JavaDoc message = "Created foreign key(s) for entity [" + entity.getEntityName() + "]";
505                         Debug.logImportant(message, module);
506                         if (messages != null) messages.add(message);
507                     }
508
509                     // show foreign key references that exist but are unknown
510
if (rcInfoMap != null) {
511                         Iterator JavaDoc rcInfoKeysLeft = rcInfoMap.keySet().iterator();
512                         while (rcInfoKeysLeft.hasNext()) {
513                             String JavaDoc rcKeyLeft = (String JavaDoc) rcInfoKeysLeft.next();
514                             String JavaDoc message = "Unknown Foreign Key Constraint " + rcKeyLeft + " found in table " + entity.getTableName(datasourceInfo);
515                             Debug.logImportant(message, module);
516                             if (messages != null) messages.add(message);
517                         }
518                     }
519                 }
520             }
521             if (Debug.infoOn()) Debug.logInfo("Created " + numFksCreated + " fk refs", module);
522         }
523
524         // make sure each one-relation has an index
525
if (checkFkIdx) {
526         //if (!justColumns && datasourceInfo.useFkIndices && datasourceInfo.checkFkIndicesOnStart) {
527
int numIndicesCreated = 0;
528             // TODO: check each key-map to make sure it exists in the index, if any differences warn and then remove the index and recreate it
529

530             // TODO: also check the declared indices on start, if the datasourceInfo.checkIndicesOnStart flag is set
531

532             // get ALL column info, put into hashmap by table name
533
Map JavaDoc tableIndexListMap = this.getIndexInfo(indexTableNames, messages);
534
535             // Debug.logVerbose("Ref Info Map: " + refTableInfoMap, module);
536

537             if (tableIndexListMap == null) {
538                 // uh oh, something happened while getting info...
539
if (Debug.verboseOn()) Debug.logVerbose("Ref Table Info Map is null", module);
540             } else {
541                 Iterator JavaDoc refModelEntityIter = modelEntityList.iterator();
542                 while (refModelEntityIter.hasNext()) {
543                     ModelEntity entity = (ModelEntity) refModelEntityIter.next();
544                     String JavaDoc entityName = entity.getEntityName();
545                     // if this is a view entity, do not check it...
546
if (entity instanceof ModelViewEntity) {
547                         String JavaDoc entMessage = "NOT Checking View Entity " + entity.getEntityName();
548                         Debug.logVerbose(entMessage, module);
549                         if (messages != null) messages.add(entMessage);
550                         continue;
551                     }
552
553                     // get existing index list for this table
554
TreeSet JavaDoc tableIndexList = (TreeSet JavaDoc) tableIndexListMap.get(entity.getTableName(datasourceInfo));
555
556                     // Debug.logVerbose("Got ind info for table " + entity.getTableName(datasourceInfo) + ": " + tableIndexList, module);
557

558                     if (tableIndexList == null) {
559                         // evidently no indexes in the database for this table, do the create all
560
this.createForeignKeyIndices(entity, datasourceInfo.constraintNameClipLength, messages);
561                     } else {
562                         // go through each relation to see if an FK already exists
563
boolean createdConstraints = false;
564                         Iterator JavaDoc relations = entity.getRelationsIterator();
565                         while (relations.hasNext()) {
566                             ModelRelation modelRelation = (ModelRelation) relations.next();
567                             if (!"one".equals(modelRelation.getType())) {
568                                 continue;
569                             }
570
571                             String JavaDoc relConstraintName = makeFkConstraintName(modelRelation, datasourceInfo.constraintNameClipLength);
572                             if (tableIndexList.contains(relConstraintName)) {
573                                 tableIndexList.remove(relConstraintName);
574                             } else {
575                                 // if not, create one
576
String JavaDoc noIdxMessage = "No Index [" + relConstraintName + "] found for entity [" + entityName + "]";
577                                 if (messages != null) messages.add(noIdxMessage);
578                                 if (Debug.infoOn()) Debug.logInfo(noIdxMessage, module);
579
580                                 if (addMissing) {
581                                     String JavaDoc errMsg = createForeignKeyIndex(entity, modelRelation, datasourceInfo.constraintNameClipLength);
582                                     if (errMsg != null && errMsg.length() > 0) {
583                                         String JavaDoc message = "Could not create foreign key index " + relConstraintName + " for entity [" + entity.getEntityName() + "]: " + errMsg;
584                                         Debug.logError(message, module);
585                                         if (messages != null) messages.add(message);
586                                     } else {
587                                         String JavaDoc message = "Created foreign key index " + relConstraintName + " for entity [" + entity.getEntityName() + "]";
588                                         Debug.logVerbose(message, module);
589                                         if (messages != null) messages.add(message);
590                                         createdConstraints = true;
591                                         numIndicesCreated++;
592                                     }
593                                 }
594                             }
595                         }
596                         if (createdConstraints) {
597                             String JavaDoc message = "Created foreign key index/indices for entity [" + entity.getEntityName() + "]";
598                             Debug.logImportant(message, module);
599                             if (messages != null) messages.add(message);
600                         }
601                     }
602
603                     // show foreign key references that exist but are unknown
604
if (tableIndexList != null) {
605                         Iterator JavaDoc tableIndexListIter = tableIndexList.iterator();
606                         while (tableIndexListIter.hasNext()) {
607                             String JavaDoc indexLeft = (String JavaDoc) tableIndexListIter.next();
608                             String JavaDoc message = "Unknown Index " + indexLeft + " found in table " + entity.getTableName(datasourceInfo);
609                             Debug.logImportant(message, module);
610                             if (messages != null) messages.add(message);
611                         }
612                     }
613                 }
614             }
615             if (Debug.infoOn()) Debug.logInfo("Created " + numIndicesCreated + " indices", module);
616         }
617
618         timer.timerString("Finished Checking Entity Database");
619     }
620
621     /** Creates a list of ModelEntity objects based on meta data from the database */
622     public List JavaDoc induceModelFromDb(Collection JavaDoc messages) {
623         // get ALL tables from this database
624
TreeSet JavaDoc tableNames = this.getTableNames(messages);
625
626         // get ALL column info, put into hashmap by table name
627
Map JavaDoc colInfo = this.getColumnInfo(tableNames, true, messages);
628
629         // go through each table and make a ModelEntity object, add to list
630
// for each entity make corresponding ModelField objects
631
// then print out XML for the entities/fields
632
List JavaDoc newEntList = FastList.newInstance();
633
634         boolean isCaseSensitive = false;
635         DatabaseMetaData JavaDoc dbData = this.getDatabaseMetaData(null, messages);
636         if (dbData != null) {
637             try {
638                 isCaseSensitive = dbData.supportsMixedCaseIdentifiers();
639             } catch (SQLException JavaDoc e) {
640                 Debug.logError(e, "Error getting db meta data about case sensitive", module);
641             }
642         }
643
644         // iterate over the table names is alphabetical order
645
Iterator JavaDoc tableNamesIter = new TreeSet JavaDoc(colInfo.keySet()).iterator();
646         while (tableNamesIter.hasNext()) {
647             String JavaDoc tableName = (String JavaDoc) tableNamesIter.next();
648             Map JavaDoc colMap = (Map JavaDoc) colInfo.get(tableName);
649             ModelEntity newEntity = new ModelEntity(tableName, colMap, modelFieldTypeReader, isCaseSensitive);
650             newEntList.add(newEntity);
651         }
652
653         return newEntList;
654     }
655
656     public Document JavaDoc induceModelFromDb(String JavaDoc packageName) {
657         Document JavaDoc document = UtilXml.makeEmptyXmlDocument("entitymodel");
658         Element JavaDoc root = document.getDocumentElement();
659         root.appendChild(document.createElement("title"));
660         root.appendChild(document.createElement("description"));
661         root.appendChild(document.createElement("copyright"));
662         root.appendChild(document.createElement("author"));
663         root.appendChild(document.createElement("version"));
664
665         // messages list
666
List JavaDoc messages = new ArrayList JavaDoc();
667
668         // get ALL tables from this database
669
TreeSet JavaDoc tableNames = this.getTableNames(messages);
670
671         // get ALL column info, put into hashmap by table name
672
Map JavaDoc colInfo = this.getColumnInfo(tableNames, true, messages);
673
674         boolean isCaseSensitive = false;
675         DatabaseMetaData JavaDoc dbData = this.getDatabaseMetaData(null, messages);
676         if (dbData != null) {
677             try {
678                 isCaseSensitive = dbData.supportsMixedCaseIdentifiers();
679             } catch (SQLException JavaDoc e) {
680                 Debug.logError(e, "Error getting db meta data about case sensitive", module);
681             }
682         }
683
684         if (UtilValidate.isNotEmpty(packageName)) {
685             String JavaDoc catalogName = null;
686             try {
687                 catalogName = this.getConnection().getCatalog();
688             } catch (Exception JavaDoc e) {
689                 // ignore
690
}
691             packageName = "org.ofbiz.ext." + (catalogName != null ? catalogName : "unknown");
692         }
693
694
695         // iterate over the table names is alphabetical order
696
Iterator JavaDoc tableNamesIter = new TreeSet JavaDoc(colInfo.keySet()).iterator();
697         while (tableNamesIter.hasNext()) {
698             String JavaDoc tableName = (String JavaDoc) tableNamesIter.next();
699             Map JavaDoc colMap = (Map JavaDoc) colInfo.get(tableName);
700             ModelEntity newEntity = new ModelEntity(tableName, colMap, modelFieldTypeReader, isCaseSensitive);
701             root.appendChild(newEntity.toXmlElement(document, "org.ofbiz.ext." + packageName));
702         }
703
704         // print the messages to the console
705
for (int i = 0; i < messages.size(); i++) {
706             Debug.logInfo((String JavaDoc) messages.get(i), module);
707         }
708         return document;
709     }
710
711     public Document JavaDoc induceModelFromDb() {
712         return this.induceModelFromDb("");
713     }
714
715     public DatabaseMetaData JavaDoc getDatabaseMetaData(Connection JavaDoc connection, Collection JavaDoc messages) {
716         if (connection == null) {
717             try {
718                 connection = getConnection();
719             } catch (SQLException JavaDoc sqle) {
720                 String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + sqle.toString();
721                 Debug.logError(message, module);
722                 if (messages != null) messages.add(message);
723                 return null;
724             } catch (GenericEntityException e) {
725                 String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + e.toString();
726                 Debug.logError(message, module);
727                 if (messages != null) messages.add(message);
728                 return null;
729             }
730         }
731
732         if (connection == null) {
733             String JavaDoc message = "Unable to esablish a connection with the database, no additional information available.";
734             Debug.logError(message, module);
735             if (messages != null) messages.add(message);
736             return null;
737         }
738
739         DatabaseMetaData JavaDoc dbData = null;
740         try {
741             dbData = connection.getMetaData();
742         } catch (SQLException JavaDoc sqle) {
743             String JavaDoc message = "Unable to get database meta data... Error was:" + sqle.toString();
744             Debug.logError(message, module);
745             if (messages != null) {
746                 messages.add(message);
747             }
748             return null;
749         }
750
751         if (dbData == null) {
752             Debug.logWarning("Unable to get database meta data; method returned null", module);
753         }
754
755         return dbData;
756     }
757
758     public void printDbMiscData(DatabaseMetaData JavaDoc dbData, Connection JavaDoc con) {
759         if (dbData == null) {
760             return;
761         }
762         // Database Info
763
if (Debug.infoOn()) {
764             try {
765                 Debug.logInfo("Database Product Name is " + dbData.getDatabaseProductName(), module);
766                 Debug.logInfo("Database Product Version is " + dbData.getDatabaseProductVersion(), module);
767             } catch (SQLException JavaDoc sqle) {
768                 Debug.logWarning("Unable to get Database name & version information", module);
769             }
770         }
771         // JDBC Driver Info
772
if (Debug.infoOn()) {
773             try {
774                 Debug.logInfo("Database Driver Name is " + dbData.getDriverName(), module);
775                 Debug.logInfo("Database Driver Version is " + dbData.getDriverVersion(), module);
776                 Debug.logInfo("Database Driver JDBC Version is " + dbData.getJDBCMajorVersion() + "." + dbData.getJDBCMinorVersion(), module);
777             } catch (SQLException JavaDoc sqle) {
778                 Debug.logWarning("Unable to get Driver name & version information", module);
779             } catch (AbstractMethodError JavaDoc ame) {
780                 Debug.logWarning("Unable to get Driver JDBC Version", module);
781             }
782         }
783         // Db/Driver support settings
784
if (Debug.infoOn()) {
785             try {
786                 Debug.logInfo("Database Setting/Support Information (those with a * should be true):", module);
787                 Debug.logInfo("- supports transactions [" + dbData.supportsTransactions() + "]*", module);
788                 Debug.logInfo("- isolation None [" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_NONE) + "]", module);
789                 Debug.logInfo("- isolation ReadCommitted [" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_COMMITTED) + "]", module);
790                 Debug.logInfo("- isolation ReadUncommitted[" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_UNCOMMITTED) + "]", module);
791                 Debug.logInfo("- isolation RepeatableRead [" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_REPEATABLE_READ) + "]", module);
792                 Debug.logInfo("- isolation Serializable [" + dbData.supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE) + "]", module);
793                 Debug.logInfo("- default fetchsize [" + con.createStatement().getFetchSize() + "]", module);
794                 Debug.logInfo("- forward only type [" + dbData.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY) + "]", module);
795                 Debug.logInfo("- scroll sensitive type [" + dbData.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE) + "]", module);
796                 Debug.logInfo("- scroll insensitive type [" + dbData.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE) + "]", module);
797                 Debug.logInfo("- is case sensitive [" + dbData.supportsMixedCaseIdentifiers() + "]", module);
798                 Debug.logInfo("- stores LowerCase [" + dbData.storesLowerCaseIdentifiers() + "]", module);
799                 Debug.logInfo("- stores MixedCase [" + dbData.storesMixedCaseIdentifiers() + "]", module);
800                 Debug.logInfo("- stores UpperCase [" + dbData.storesUpperCaseIdentifiers() + "]", module);
801                 Debug.logInfo("- max table name length [" + dbData.getMaxTableNameLength() + "]", module);
802                 Debug.logInfo("- max column name length [" + dbData.getMaxColumnNameLength() + "]", module);
803                 Debug.logInfo("- max schema name length [" + dbData.getMaxSchemaNameLength() + "]", module);
804                 Debug.logInfo("- concurrent connections [" + dbData.getMaxConnections() + "]", module);
805                 Debug.logInfo("- concurrent statements [" + dbData.getMaxStatements() + "]", module);
806                 Debug.logInfo("- ANSI SQL92 Entry [" + dbData.supportsANSI92EntryLevelSQL() + "]", module);
807                 Debug.logInfo("- ANSI SQL92 Itermediate [" + dbData.supportsANSI92IntermediateSQL() + "]", module);
808                 Debug.logInfo("- ANSI SQL92 Full [" + dbData.supportsANSI92FullSQL() + "]", module);
809                 Debug.logInfo("- ODBC SQL Grammar Core [" + dbData.supportsCoreSQLGrammar() + "]", module);
810                 Debug.logInfo("- ODBC SQL Grammar Extended[" + dbData.supportsExtendedSQLGrammar() + "]", module);
811                 Debug.logInfo("- ODBC SQL Grammar Minimum [" + dbData.supportsMinimumSQLGrammar() + "]", module);
812                 Debug.logInfo("- outer joins [" + dbData.supportsOuterJoins() + "]*", module);
813                 Debug.logInfo("- limited outer joins [" + dbData.supportsLimitedOuterJoins() + "]", module);
814                 Debug.logInfo("- full outer joins [" + dbData.supportsFullOuterJoins() + "]", module);
815                 Debug.logInfo("- group by [" + dbData.supportsGroupBy() + "]*", module);
816                 Debug.logInfo("- group by not in select [" + dbData.supportsGroupByUnrelated() + "]", module);
817                 Debug.logInfo("- column aliasing [" + dbData.supportsColumnAliasing() + "]", module);
818                 Debug.logInfo("- order by not in select [" + dbData.supportsOrderByUnrelated() + "]", module);
819                 // this doesn't work in HSQLDB, other databases? Debug.logInfo("- named parameters [" + dbData.supportsNamedParameters() + "]", module);
820
Debug.logInfo("- alter table add column [" + dbData.supportsAlterTableWithAddColumn() + "]*", module);
821                 Debug.logInfo("- non-nullable column [" + dbData.supportsNonNullableColumns() + "]*", module);
822             } catch (Exception JavaDoc e) {
823                 Debug.logWarning(e, "Unable to get misc. support/setting information", module);
824             }
825         }
826     }
827
828     public TreeSet JavaDoc getTableNames(Collection JavaDoc messages) {
829         Connection JavaDoc connection = null;
830
831         try {
832             connection = getConnection();
833         } catch (SQLException JavaDoc sqle) {
834             String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + sqle.toString();
835             Debug.logError(message, module);
836             if (messages != null) messages.add(message);
837             return null;
838         } catch (GenericEntityException e) {
839             String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + e.toString();
840             Debug.logError(message, module);
841             if (messages != null) messages.add(message);
842             return null;
843         }
844
845         if (connection == null) {
846             String JavaDoc message = "Unable to esablish a connection with the database, no additional information available.";
847             Debug.logError(message, module);
848             if (messages != null) messages.add(message);
849             return null;
850         }
851
852         DatabaseMetaData JavaDoc dbData = this.getDatabaseMetaData(connection, messages);
853         if (dbData == null) {
854             return null;
855         }
856
857         printDbMiscData(dbData, connection);
858         if (Debug.infoOn()) Debug.logInfo("Getting Table Info From Database", module);
859
860         // get ALL tables from this database
861
TreeSet JavaDoc tableNames = new TreeSet JavaDoc();
862         ResultSet JavaDoc tableSet = null;
863
864         String JavaDoc lookupSchemaName = null;
865         try {
866             String JavaDoc[] types = {"TABLE", "VIEW", "ALIAS", "SYNONYM"};
867             lookupSchemaName = getSchemaName(dbData);
868             tableSet = dbData.getTables(null, lookupSchemaName, null, types);
869             if (tableSet == null) {
870                 Debug.logWarning("getTables returned null set", module);
871             }
872         } catch (SQLException JavaDoc sqle) {
873             String JavaDoc message = "Unable to get list of table information, let's try the create anyway... Error was:" + sqle.toString();
874             Debug.logError(message, module);
875             if (messages != null) messages.add(message);
876
877             try {
878                 connection.close();
879             } catch (SQLException JavaDoc sqle2) {
880                 String JavaDoc message2 = "Unable to close database connection, continuing anyway... Error was:" + sqle2.toString();
881                 Debug.logError(message2, module);
882                 if (messages != null) messages.add(message2);
883             }
884             // we are returning an empty set here because databases like SapDB throw an exception when there are no tables in the database
885
return tableNames;
886         }
887
888         try {
889             boolean needsUpperCase = false;
890             try {
891                 needsUpperCase = dbData.storesLowerCaseIdentifiers() || dbData.storesMixedCaseIdentifiers();
892             } catch (SQLException JavaDoc sqle) {
893                 String JavaDoc message = "Error getting identifier case information... Error was:" + sqle.toString();
894                 Debug.logError(message, module);
895                 if (messages != null) messages.add(message);
896             }
897             while (tableSet.next()) {
898                 try {
899                     String JavaDoc tableName = tableSet.getString("TABLE_NAME");
900                     // for those databases which do not return the schema name with the table name (pgsql 7.3)
901
boolean appendSchemaName = false;
902                     if (tableName != null && lookupSchemaName != null && !tableName.startsWith(lookupSchemaName)) {
903                         appendSchemaName = true;
904                     }
905                     if (needsUpperCase && tableName != null) {
906                         tableName = tableName.toUpperCase();
907                     }
908                     if (appendSchemaName) {
909                         tableName = lookupSchemaName + "." + tableName;
910                     }
911
912                     // NOTE: this may need a toUpperCase in some cases, keep an eye on it, okay for now just do a compare with equalsIgnoreCase
913
String JavaDoc tableType = tableSet.getString("TABLE_TYPE");
914                     // only allow certain table types
915
if (tableType != null && !"TABLE".equalsIgnoreCase(tableType) && !"VIEW".equalsIgnoreCase(tableType) && !"ALIAS".equalsIgnoreCase(tableType) && !"SYNONYM".equalsIgnoreCase(tableType)) {
916                         continue;
917                     }
918
919                     // String remarks = tableSet.getString("REMARKS");
920
tableNames.add(tableName);
921                     // if (Debug.infoOn()) Debug.logInfo("Found table named [" + tableName + "] of type [" + tableType + "] with remarks: " + remarks, module);
922
} catch (SQLException JavaDoc sqle) {
923                     String JavaDoc message = "Error getting table information... Error was:" + sqle.toString();
924                     Debug.logError(message, module);
925                     if (messages != null) messages.add(message);
926                     continue;
927                 }
928             }
929         } catch (SQLException JavaDoc sqle) {
930             String JavaDoc message = "Error getting next table information... Error was:" + sqle.toString();
931             Debug.logError(message, module);
932             if (messages != null) messages.add(message);
933         } finally {
934             try {
935                 tableSet.close();
936             } catch (SQLException JavaDoc sqle) {
937                 String JavaDoc message = "Unable to close ResultSet for table list, continuing anyway... Error was:" + sqle.toString();
938                 Debug.logError(message, module);
939                 if (messages != null) messages.add(message);
940             }
941
942             try {
943                 connection.close();
944             } catch (SQLException JavaDoc sqle) {
945                 String JavaDoc message = "Unable to close database connection, continuing anyway... Error was:" + sqle.toString();
946                 Debug.logError(message, module);
947                 if (messages != null) messages.add(message);
948             }
949         }
950         return tableNames;
951     }
952
953     public Map JavaDoc getColumnInfo(Set JavaDoc tableNames, boolean getPks, Collection JavaDoc messages) {
954         // if there are no tableNames, don't even try to get the columns
955
if (tableNames.size() == 0) {
956             return FastMap.newInstance();
957         }
958
959         Connection JavaDoc connection = null;
960         try {
961             try {
962                 connection = getConnection();
963             } catch (SQLException JavaDoc sqle) {
964                 String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + sqle.toString();
965                 Debug.logError(message, module);
966                 if (messages != null) messages.add(message);
967                 return null;
968             } catch (GenericEntityException e) {
969                 String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + e.toString();
970                 Debug.logError(message, module);
971                 if (messages != null) messages.add(message);
972                 return null;
973             }
974
975             DatabaseMetaData JavaDoc dbData = null;
976             try {
977                 dbData = connection.getMetaData();
978             } catch (SQLException JavaDoc sqle) {
979                 String JavaDoc message = "Unable to get database meta data... Error was:" + sqle.toString();
980                 Debug.logError(message, module);
981                 if (messages != null) messages.add(message);
982
983                 try {
984                     connection.close();
985                 } catch (SQLException JavaDoc sqle2) {
986                     String JavaDoc message2 = "Unable to close database connection, continuing anyway... Error was:" + sqle2.toString();
987                     Debug.logError(message2, module);
988                     if (messages != null) messages.add(message2);
989                 }
990                 return null;
991             }
992
993             if (Debug.infoOn()) Debug.logInfo("Getting Column Info From Database", module);
994
995             Map JavaDoc colInfo = FastMap.newInstance();
996             String JavaDoc lookupSchemaName = null;
997             try {
998                 if (dbData.supportsSchemasInTableDefinitions()) {
999                     if (this.datasourceInfo.schemaName != null && this.datasourceInfo.schemaName.length() > 0) {
1000                        lookupSchemaName = this.datasourceInfo.schemaName;
1001                    } else {
1002                        lookupSchemaName = dbData.getUserName();
1003                    }
1004                }
1005
1006                boolean needsUpperCase = false;
1007                try {
1008                    needsUpperCase = dbData.storesLowerCaseIdentifiers() || dbData.storesMixedCaseIdentifiers();
1009                } catch (SQLException JavaDoc sqle) {
1010                    String JavaDoc message = "Error getting identifier case information... Error was:" + sqle.toString();
1011                    Debug.logError(message, module);
1012                    if (messages != null) messages.add(message);
1013                }
1014
1015                boolean foundCols = false;
1016                ResultSet JavaDoc rsCols = dbData.getColumns(null, lookupSchemaName, null, null);
1017                if (!rsCols.next()) {
1018                    try {
1019                        rsCols.close();
1020                    } catch (SQLException JavaDoc sqle) {
1021                        String JavaDoc message = "Unable to close ResultSet for column list, continuing anyway... Error was:" + sqle.toString();
1022                        Debug.logError(message, module);
1023                        if (messages != null) messages.add(message);
1024                    }
1025                    rsCols = dbData.getColumns(null, lookupSchemaName, "%", "%");
1026                    if (!rsCols.next()) {
1027                        // TODO: now what to do? I guess try one table name at a time...
1028
} else {
1029                        foundCols = true;
1030                    }
1031                } else {
1032                    foundCols = true;
1033                }
1034                if (foundCols) {
1035                    do {
1036                        try {
1037                            ColumnCheckInfo ccInfo = new ColumnCheckInfo();
1038
1039                            ccInfo.tableName = ColumnCheckInfo.fixupTableName(rsCols.getString("TABLE_NAME"), lookupSchemaName, needsUpperCase);
1040                            // ignore the column info if the table name is not in the list we are concerned with
1041
if (!tableNames.contains(ccInfo.tableName)) {
1042                                continue;
1043                            }
1044
1045                            ccInfo.columnName = rsCols.getString("COLUMN_NAME");
1046                            if (needsUpperCase && ccInfo.columnName != null) {
1047                                ccInfo.columnName = ccInfo.columnName.toUpperCase();
1048                            }
1049                            // NOTE: this may need a toUpperCase in some cases, keep an eye on it
1050
ccInfo.typeName = rsCols.getString("TYPE_NAME");
1051                            ccInfo.columnSize = rsCols.getInt("COLUMN_SIZE");
1052                            ccInfo.decimalDigits = rsCols.getInt("DECIMAL_DIGITS");
1053                            // NOTE: this may need a toUpperCase in some cases, keep an eye on it
1054
ccInfo.isNullable = rsCols.getString("IS_NULLABLE");
1055
1056                            Map JavaDoc tableColInfo = (Map JavaDoc) colInfo.get(ccInfo.tableName);
1057                            if (tableColInfo == null) {
1058                                tableColInfo = FastMap.newInstance();
1059                                colInfo.put(ccInfo.tableName, tableColInfo);
1060                            }
1061                            tableColInfo.put(ccInfo.columnName, ccInfo);
1062                        } catch (SQLException JavaDoc sqle) {
1063                            String JavaDoc message = "Error getting column info for column. Error was:" + sqle.toString();
1064                            Debug.logError(message, module);
1065                            if (messages != null) messages.add(message);
1066                            continue;
1067                        }
1068                    } while (rsCols.next());
1069                }
1070
1071                try {
1072                    rsCols.close();
1073                } catch (SQLException JavaDoc sqle) {
1074                    String JavaDoc message = "Unable to close ResultSet for column list, continuing anyway... Error was:" + sqle.toString();
1075                    Debug.logError(message, module);
1076                    if (messages != null) messages.add(message);
1077                }
1078
1079                if (getPks) {
1080                    boolean foundPks = false;
1081                    ResultSet JavaDoc rsPks = dbData.getPrimaryKeys(null, lookupSchemaName, null);
1082                    if (!rsPks.next()) {
1083                        try {
1084                            rsPks.close();
1085                        } catch (SQLException JavaDoc sqle) {
1086                            String JavaDoc message = "Unable to close ResultSet for primary key list, continuing anyway... Error was:" + sqle.toString();
1087                            Debug.logError(message, module);
1088                            if (messages != null) messages.add(message);
1089                        }
1090                        rsPks = dbData.getPrimaryKeys(null, lookupSchemaName, "%");
1091                        if (!rsPks.next()) {
1092                            // TODO: now what to do? I guess try one table name at a time...
1093
} else {
1094                            foundPks = true;
1095                        }
1096                    } else {
1097                        foundPks = true;
1098                    }
1099                    if (foundPks) {
1100                        do {
1101                            try {
1102                                String JavaDoc tableName = ColumnCheckInfo.fixupTableName(rsPks.getString("TABLE_NAME"), lookupSchemaName, needsUpperCase);
1103                                String JavaDoc columnName = rsPks.getString("COLUMN_NAME");
1104                                if (needsUpperCase && columnName != null) {
1105                                    columnName = columnName.toUpperCase();
1106                                }
1107                                Map JavaDoc tableColInfo = (Map JavaDoc) colInfo.get(tableName);
1108                                if (tableColInfo == null) {
1109                                    // not looking for info on this table
1110
continue;
1111                                }
1112                                ColumnCheckInfo ccInfo = (ColumnCheckInfo) tableColInfo.get(columnName);
1113                                if (ccInfo == null) {
1114                                    // this isn't good, what to do?
1115
Debug.logWarning("Got primary key information for a column that we didn't get column information for: tableName=[" + tableName + "], columnName=[" + columnName + "]", module);
1116                                    continue;
1117                                }
1118
1119                                /*
1120                                KEY_SEQ short => sequence number within primary key
1121                                PK_NAME String => primary key name (may be null)
1122                                */

1123                                ccInfo.isPk = true;
1124                                ccInfo.pkSeq = rsPks.getShort("KEY_SEQ");
1125                                ccInfo.pkName = rsPks.getString("PK_NAME");
1126                            } catch (SQLException JavaDoc sqle) {
1127                                String JavaDoc message = "Error getting primary key info for column. Error was:" + sqle.toString();
1128                                Debug.logError(message, module);
1129                                if (messages != null) messages.add(message);
1130                                continue;
1131                            }
1132                        } while (rsPks.next());
1133                    }
1134
1135                    try {
1136                        rsPks.close();
1137                    } catch (SQLException JavaDoc sqle) {
1138                        String JavaDoc message = "Unable to close ResultSet for primary key list, continuing anyway... Error was:" + sqle.toString();
1139                        Debug.logError(message, module);
1140                        if (messages != null) messages.add(message);
1141                    }
1142                }
1143            } catch (SQLException JavaDoc sqle) {
1144                String JavaDoc message = "Error getting column meta data for Error was:" + sqle.toString() + ". Not checking columns.";
1145                Debug.logError(message, module);
1146                if (messages != null) messages.add(message);
1147                // we are returning an empty set in this case because databases like SapDB throw an exception when there are no tables in the database
1148
// colInfo = null;
1149
}
1150            return colInfo;
1151        } finally {
1152            if (connection != null) {
1153                try {
1154                    connection.close();
1155                } catch (SQLException JavaDoc sqle) {
1156                    String JavaDoc message = "Unable to close database connection, continuing anyway... Error was:" + sqle.toString();
1157                    Debug.logError(message, module);
1158                    if (messages != null) messages.add(message);
1159                }
1160            }
1161        }
1162    }
1163
1164    public Map JavaDoc getReferenceInfo(Set JavaDoc tableNames, Collection JavaDoc messages) {
1165        Connection JavaDoc connection = null;
1166        try {
1167            connection = getConnection();
1168        } catch (SQLException JavaDoc sqle) {
1169            String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + sqle.toString();
1170            Debug.logError(message, module);
1171            if (messages != null) messages.add(message);
1172            return null;
1173        } catch (GenericEntityException e) {
1174            String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + e.toString();
1175            Debug.logError(message, module);
1176            if (messages != null) messages.add(message);
1177            return null;
1178        }
1179
1180        DatabaseMetaData JavaDoc dbData = null;
1181        try {
1182            dbData = connection.getMetaData();
1183        } catch (SQLException JavaDoc sqle) {
1184            String JavaDoc message = "Unable to get database meta data... Error was:" + sqle.toString();
1185            Debug.logError(message, module);
1186            if (messages != null) messages.add(message);
1187
1188            try {
1189                connection.close();
1190            } catch (SQLException JavaDoc sqle2) {
1191                String JavaDoc message2 = "Unable to close database connection, continuing anyway... Error was:" + sqle2.toString();
1192                Debug.logError(message2, module);
1193                if (messages != null) messages.add(message2);
1194            }
1195            return null;
1196        }
1197
1198        /*
1199         try {
1200         if (Debug.infoOn()) Debug.logInfo("Database Product Name is " + dbData.getDatabaseProductName(), module);
1201         if (Debug.infoOn()) Debug.logInfo("Database Product Version is " + dbData.getDatabaseProductVersion(), module);
1202         } catch (SQLException sqle) {
1203         Debug.logWarning("Unable to get Database name & version information", module);
1204         }
1205         try {
1206         if (Debug.infoOn()) Debug.logInfo("Database Driver Name is " + dbData.getDriverName(), module);
1207         if (Debug.infoOn()) Debug.logInfo("Database Driver Version is " + dbData.getDriverVersion(), module);
1208         } catch (SQLException sqle) {
1209         Debug.logWarning("Unable to get Driver name & version information", module);
1210         }
1211         */

1212
1213        if (Debug.infoOn()) Debug.logInfo("Getting Foreign Key (Reference) Info From Database", module);
1214
1215        Map JavaDoc refInfo = FastMap.newInstance();
1216
1217        try {
1218            // ResultSet rsCols = dbData.getCrossReference(null, null, null, null, null, null);
1219
String JavaDoc lookupSchemaName = null;
1220            if (dbData.supportsSchemasInTableDefinitions()) {
1221                if (this.datasourceInfo.schemaName != null && this.datasourceInfo.schemaName.length() > 0) {
1222                    lookupSchemaName = this.datasourceInfo.schemaName;
1223                } else {
1224                    lookupSchemaName = dbData.getUserName();
1225                }
1226            }
1227
1228            boolean needsUpperCase = false;
1229            try {
1230                needsUpperCase = dbData.storesLowerCaseIdentifiers() || dbData.storesMixedCaseIdentifiers();
1231            } catch (SQLException JavaDoc sqle) {
1232                String JavaDoc message = "Error getting identifier case information... Error was:" + sqle.toString();
1233                Debug.logError(message, module);
1234                if (messages != null) messages.add(message);
1235            }
1236
1237            ResultSet JavaDoc rsCols = dbData.getImportedKeys(null, lookupSchemaName, null);
1238            int totalFkRefs = 0;
1239
1240            // Iterator tableNamesIter = tableNames.iterator();
1241
// while (tableNamesIter.hasNext()) {
1242
// String tableName = (String) tableNamesIter.next();
1243
// ResultSet rsCols = dbData.getImportedKeys(null, null, tableName);
1244
// Debug.logVerbose("Getting imported keys for table " + tableName, module);
1245

1246            while (rsCols.next()) {
1247                try {
1248                    ReferenceCheckInfo rcInfo = new ReferenceCheckInfo();
1249
1250                    rcInfo.pkTableName = rsCols.getString("PKTABLE_NAME");
1251                    if (needsUpperCase && rcInfo.pkTableName != null) {
1252                        rcInfo.pkTableName = rcInfo.pkTableName.toUpperCase();
1253                    }
1254                    rcInfo.pkColumnName = rsCols.getString("PKCOLUMN_NAME");
1255                    if (needsUpperCase && rcInfo.pkColumnName != null) {
1256                        rcInfo.pkColumnName = rcInfo.pkColumnName.toUpperCase();
1257                    }
1258
1259                    rcInfo.fkTableName = rsCols.getString("FKTABLE_NAME");
1260                    if (needsUpperCase && rcInfo.fkTableName != null) {
1261                        rcInfo.fkTableName = rcInfo.fkTableName.toUpperCase();
1262                    }
1263                    // ignore the column info if the FK table name is not in the list we are concerned with
1264
if (!tableNames.contains(rcInfo.fkTableName)) {
1265                        continue;
1266                    }
1267                    rcInfo.fkColumnName = rsCols.getString("FKCOLUMN_NAME");
1268                    if (needsUpperCase && rcInfo.fkColumnName != null) {
1269                        rcInfo.fkColumnName = rcInfo.fkColumnName.toUpperCase();
1270                    }
1271                    rcInfo.fkName = rsCols.getString("FK_NAME");
1272                    if (needsUpperCase && rcInfo.fkName != null) {
1273                        rcInfo.fkName = rcInfo.fkName.toUpperCase();
1274                    }
1275
1276                    if (Debug.verboseOn()) Debug.logVerbose("Got: " + rcInfo.toString(), module);
1277
1278                    Map JavaDoc tableRefInfo = (Map JavaDoc) refInfo.get(rcInfo.fkTableName);
1279                    if (tableRefInfo == null) {
1280                        tableRefInfo = FastMap.newInstance();
1281                        refInfo.put(rcInfo.fkTableName, tableRefInfo);
1282                        if (Debug.verboseOn()) Debug.logVerbose("Adding new Map for table: " + rcInfo.fkTableName, module);
1283                    }
1284                    if (!tableRefInfo.containsKey(rcInfo.fkName)) totalFkRefs++;
1285                    tableRefInfo.put(rcInfo.fkName, rcInfo);
1286                } catch (SQLException JavaDoc sqle) {
1287                    String JavaDoc message = "Error getting fk reference info for table. Error was:" + sqle.toString();
1288                    Debug.logError(message, module);
1289                    if (messages != null) messages.add(message);
1290                    continue;
1291                }
1292            }
1293
1294            // if (Debug.infoOn()) Debug.logInfo("There are " + totalFkRefs + " in the database", module);
1295
try {
1296                rsCols.close();
1297            } catch (SQLException JavaDoc sqle) {
1298                String JavaDoc message = "Unable to close ResultSet for fk reference list, continuing anyway... Error was:" + sqle.toString();
1299                Debug.logError(message, module);
1300                if (messages != null) messages.add(message);
1301            }
1302            // }
1303
if (Debug.infoOn()) Debug.logInfo("There are " + totalFkRefs + " foreign key refs in the database", module);
1304
1305        } catch (SQLException JavaDoc sqle) {
1306            String JavaDoc message = "Error getting fk reference meta data Error was:" + sqle.toString() + ". Not checking fk refs.";
1307            Debug.logError(message, module);
1308            if (messages != null) messages.add(message);
1309            refInfo = null;
1310        } finally {
1311            try {
1312                connection.close();
1313            } catch (SQLException JavaDoc sqle) {
1314                String JavaDoc message = "Unable to close database connection, continuing anyway... Error was:" + sqle.toString();
1315                Debug.logError(message, module);
1316                if (messages != null) messages.add(message);
1317            }
1318        }
1319        return refInfo;
1320    }
1321
1322    public Map JavaDoc getIndexInfo(Set JavaDoc tableNames, Collection JavaDoc messages) {
1323        Connection JavaDoc connection = null;
1324
1325        try {
1326            connection = getConnection();
1327        } catch (SQLException JavaDoc sqle) {
1328            String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + sqle.toString();
1329            Debug.logError(message, module);
1330            if (messages != null) messages.add(message);
1331            return null;
1332        } catch (GenericEntityException e) {
1333            String JavaDoc message = "Unable to esablish a connection with the database... Error was:" + e.toString();
1334            Debug.logError(message, module);
1335            if (messages != null) messages.add(message);
1336            return null;
1337        }
1338
1339        DatabaseMetaData JavaDoc dbData = null;
1340        try {
1341            dbData = connection.getMetaData();
1342        } catch (SQLException JavaDoc sqle) {
1343            String JavaDoc message = "Unable to get database meta data... Error was:" + sqle.toString();
1344            Debug.logError(message, module);
1345            if (messages != null) messages.add(message);
1346
1347            try {
1348                connection.close();
1349            } catch (SQLException JavaDoc sqle2) {
1350                String JavaDoc message2 = "Unable to close database connection, continuing anyway... Error was:" + sqle2.toString();
1351                Debug.logError(message2, module);
1352                if (messages != null) messages.add(message2);
1353            }
1354            return null;
1355        }
1356
1357        boolean needsUpperCase = false;
1358        try {
1359            needsUpperCase = dbData.storesLowerCaseIdentifiers() || dbData.storesMixedCaseIdentifiers();
1360        } catch (SQLException JavaDoc sqle) {
1361            String JavaDoc message = "Error getting identifier case information... Error was:" + sqle.toString();
1362            Debug.logError(message, module);
1363            if (messages != null) messages.add(message);
1364        }
1365
1366        if (Debug.infoOn()) Debug.logInfo("Getting Index Info From Database", module);
1367
1368        Map JavaDoc indexInfo = FastMap.newInstance();
1369        try {
1370            int totalIndices = 0;
1371            Iterator JavaDoc tableNamesIter = tableNames.iterator();
1372            while (tableNamesIter.hasNext()) {
1373                String JavaDoc curTableName = (String JavaDoc) tableNamesIter.next();
1374
1375                String JavaDoc lookupSchemaName = null;
1376                if (dbData.supportsSchemasInTableDefinitions()) {
1377                    if (this.datasourceInfo.schemaName != null && this.datasourceInfo.schemaName.length() > 0) {
1378                        lookupSchemaName = this.datasourceInfo.schemaName;
1379                    } else {
1380                        lookupSchemaName = dbData.getUserName();
1381                    }
1382                }
1383
1384                ResultSet JavaDoc rsCols = null;
1385                try {
1386                    // false for unique, we don't really use unique indexes
1387
// true for approximate, don't really care if stats are up-to-date
1388
rsCols = dbData.getIndexInfo(null, lookupSchemaName, curTableName, false, true);
1389                } catch (Exception JavaDoc e) {
1390                    Debug.logWarning(e, "Error getting index info for table: " + curTableName + " using lookupSchemaName " + lookupSchemaName, module);
1391                }
1392
1393                while (rsCols != null && rsCols.next()) {
1394                    // NOTE: The code in this block may look funny, but it is designed so that the wrapping loop can be removed
1395
try {
1396                        // skip all index info for statistics
1397
if (rsCols.getShort("TYPE") == DatabaseMetaData.tableIndexStatistic) continue;
1398
1399                        // HACK: for now skip all "unique" indexes since our foreign key indices are not unique, but the primary key ones are
1400
if (!rsCols.getBoolean("NON_UNIQUE")) continue;
1401
1402                        String JavaDoc tableName = rsCols.getString("TABLE_NAME");
1403                        if (needsUpperCase && tableName != null) {
1404                            tableName = tableName.toUpperCase();
1405                        }
1406                        if (!tableNames.contains(tableName)) continue;
1407
1408                        String JavaDoc indexName = rsCols.getString("INDEX_NAME");
1409                        if (needsUpperCase && indexName != null) {
1410                            indexName = indexName.toUpperCase();
1411                        }
1412
1413                        TreeSet JavaDoc tableIndexList = (TreeSet JavaDoc) indexInfo.get(tableName);
1414                        if (tableIndexList == null) {
1415                            tableIndexList = new TreeSet JavaDoc();
1416                            indexInfo.put(tableName, tableIndexList);
1417                            if (Debug.verboseOn()) Debug.logVerbose("Adding new Map for table: " + tableName, module);
1418                        }
1419                        if (!tableIndexList.contains(indexName)) totalIndices++;
1420                        tableIndexList.add(indexName);
1421                    } catch (SQLException JavaDoc sqle) {
1422                        String JavaDoc message = "Error getting fk reference info for table. Error was:" + sqle.toString();
1423                        Debug.logError(message, module);
1424                        if (messages != null) messages.add(message);
1425                        continue;
1426                    }
1427                }
1428
1429                // if (Debug.infoOn()) Debug.logInfo("There are " + totalIndices + " indices in the database", module);
1430
if (rsCols != null) {
1431                    try {
1432                        rsCols.close();
1433                    } catch (SQLException JavaDoc sqle) {
1434                        String JavaDoc message = "Unable to close ResultSet for fk reference list, continuing anyway... Error was:" + sqle.toString();
1435                        Debug.logError(message, module);
1436                        if (messages != null) messages.add(message);
1437                    }
1438                }
1439            }
1440            if (Debug.infoOn()) Debug.logInfo("There are " + totalIndices + " indices in the database", module);
1441
1442        } catch (SQLException JavaDoc sqle) {
1443            String JavaDoc message = "Error getting fk reference meta data Error was:" + sqle.toString() + ". Not checking fk refs.";
1444            Debug.logError(message, module);
1445            if (messages != null) messages.add(message);
1446            indexInfo = null;
1447        } finally {
1448            try {
1449                connection.close();
1450            } catch (SQLException JavaDoc sqle) {
1451                String JavaDoc message = "Unable to close database connection, continuing anyway... Error was:" + sqle.toString();
1452                Debug.logError(message, module);
1453                if (messages != null) messages.add(message);
1454            }
1455        }
1456        return indexInfo;
1457    }
1458
1459    /* ====================================================================== */
1460
1461    /* ====================================================================== */
1462
1463    public String JavaDoc createTable(ModelEntity entity, Map JavaDoc modelEntities, boolean addFks) {
1464        if (entity == null) {
1465            return "ModelEntity was null and is required to create a table";
1466        }
1467        if (entity instanceof ModelViewEntity) {
1468            return "ERROR: Cannot create table for a view entity";
1469        }
1470
1471        Connection JavaDoc connection = null;
1472        Statement JavaDoc stmt = null;
1473
1474        try {
1475            connection = getConnection();
1476        } catch (SQLException JavaDoc sqle) {
1477            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
1478        } catch (GenericEntityException e) {
1479            return "Unable to esablish a connection with the database... Error was: " + e.toString();
1480        }
1481
1482        StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("CREATE TABLE ");
1483        sqlBuf.append(entity.getTableName(this.datasourceInfo));
1484        sqlBuf.append(" (");
1485        Iterator JavaDoc fieldIter = entity.getFieldsIterator();
1486        while (fieldIter.hasNext()) {
1487            ModelField field = (ModelField) fieldIter.next();
1488            ModelFieldType type = modelFieldTypeReader.getModelFieldType(field.getType());
1489            if (type == null) {
1490                return "Field type [" + type + "] not found for field [" + field.getName() + "] of entity [" + entity.getEntityName() + "], not creating table.";
1491            }
1492
1493            sqlBuf.append(field.getColName());
1494            sqlBuf.append(" ");
1495            sqlBuf.append(type.getSqlType());
1496
1497            if("String".equals(type.getJavaType()) || "java.lang.String".equals(type.getJavaType())) {
1498                // if there is a characterSet, add the CHARACTER SET arg here
1499
if (UtilValidate.isNotEmpty(this.datasourceInfo.characterSet)) {
1500                    sqlBuf.append(" CHARACTER SET ");
1501                    sqlBuf.append(this.datasourceInfo.characterSet);
1502                }
1503                // if there is a collate, add the COLLATE arg here
1504
if (UtilValidate.isNotEmpty(this.datasourceInfo.collate)) {
1505                    sqlBuf.append(" COLLATE ");
1506                    sqlBuf.append(this.datasourceInfo.collate);
1507                }
1508            }
1509
1510            if (field.getIsPk()) {
1511                if (this.datasourceInfo.alwaysUseConstraintKeyword) {
1512                    sqlBuf.append(" CONSTRAINT NOT NULL, ");
1513                } else {
1514                    sqlBuf.append(" NOT NULL, ");
1515                }
1516            } else {
1517                sqlBuf.append(", ");
1518            }
1519        }
1520
1521        String JavaDoc pkName = makePkConstraintName(entity, this.datasourceInfo.constraintNameClipLength);
1522        if (this.datasourceInfo.usePkConstraintNames) {
1523            sqlBuf.append("CONSTRAINT ");
1524            sqlBuf.append(pkName);
1525        }
1526        sqlBuf.append(" PRIMARY KEY (");
1527        sqlBuf.append(entity.colNameString(entity.getPksCopy()));
1528        sqlBuf.append(")");
1529
1530        if (addFks) {
1531            // NOTE: This is kind of a bad idea anyway since ordering table creations is crazy, if not impossible
1532

1533            // go through the relationships to see if any foreign keys need to be added
1534
Iterator JavaDoc relationsIter = entity.getRelationsIterator();
1535            while (relationsIter.hasNext()) {
1536                ModelRelation modelRelation = (ModelRelation) relationsIter.next();
1537                if ("one".equals(modelRelation.getType())) {
1538                    ModelEntity relModelEntity = (ModelEntity) modelEntities.get(modelRelation.getRelEntityName());
1539                    if (relModelEntity == null) {
1540                        Debug.logError("Error adding foreign key: ModelEntity was null for related entity name " + modelRelation.getRelEntityName(), module);
1541                        continue;
1542                    }
1543                    if (relModelEntity instanceof ModelViewEntity) {
1544                        Debug.logError("Error adding foreign key: related entity is a view entity for related entity name " + modelRelation.getRelEntityName(), module);
1545                        continue;
1546                    }
1547
1548                    String JavaDoc fkConstraintClause = makeFkConstraintClause(entity, modelRelation, relModelEntity, this.datasourceInfo.constraintNameClipLength, this.datasourceInfo.fkStyle, this.datasourceInfo.useFkInitiallyDeferred);
1549                    if (UtilValidate.isNotEmpty(fkConstraintClause)) {
1550                        sqlBuf.append(", ");
1551                        sqlBuf.append(fkConstraintClause);
1552                    } else {
1553                        continue;
1554                    }
1555                }
1556            }
1557        }
1558
1559        sqlBuf.append(")");
1560
1561        // if there is a tableType, add the TYPE arg here
1562
if (UtilValidate.isNotEmpty(this.datasourceInfo.tableType)) {
1563            sqlBuf.append(" TYPE ");
1564            sqlBuf.append(this.datasourceInfo.tableType);
1565        }
1566
1567        // if there is a characterSet, add the CHARACTER SET arg here
1568
if (UtilValidate.isNotEmpty(this.datasourceInfo.characterSet)) {
1569            sqlBuf.append(" CHARACTER SET ");
1570            sqlBuf.append(this.datasourceInfo.characterSet);
1571        }
1572
1573        // if there is a collate, add the COLLATE arg here
1574
if (UtilValidate.isNotEmpty(this.datasourceInfo.collate)) {
1575            sqlBuf.append(" COLLATE ");
1576            sqlBuf.append(this.datasourceInfo.collate);
1577        }
1578
1579        if (Debug.verboseOn()) Debug.logVerbose("[createTable] sql=" + sqlBuf.toString(), module);
1580        try {
1581            stmt = connection.createStatement();
1582            stmt.executeUpdate(sqlBuf.toString());
1583        } catch (SQLException JavaDoc sqle) {
1584            return "SQL Exception while executing the following:\n" + sqlBuf.toString() + "\nError was: " + sqle.toString();
1585        } finally {
1586            try {
1587                if (stmt != null) stmt.close();
1588            } catch (SQLException JavaDoc sqle) {
1589                Debug.logError(sqle, module);
1590            }
1591            try {
1592                if (connection != null) {
1593                    connection.close();
1594                }
1595            } catch (SQLException JavaDoc sqle) {
1596                Debug.logError(sqle, module);
1597            }
1598        }
1599        return null;
1600    }
1601
1602    public void deleteTable(ModelEntity entity, List JavaDoc messages) {
1603        if (entity == null) {
1604            String JavaDoc errMsg = "ModelEntity was null and is required to delete a table";
1605            Debug.logError(errMsg, module);
1606            if (messages != null) messages.add(errMsg);
1607            return;
1608        }
1609        if (entity instanceof ModelViewEntity) {
1610            //String errMsg = "ERROR: Cannot delete table for a view entity";
1611
//Debug.logError(errMsg, module);
1612
//if (messages != null) messages.add(errMsg);
1613
return;
1614        }
1615
1616        Connection JavaDoc connection = null;
1617        Statement JavaDoc stmt = null;
1618        try {
1619            connection = getConnection();
1620        } catch (SQLException JavaDoc sqle) {
1621            String JavaDoc errMsg = "Unable to esablish a connection with the database... Error was: " + sqle.toString();
1622            Debug.logError(errMsg, module);
1623            if (messages != null) messages.add(errMsg);
1624            return;
1625        } catch (GenericEntityException e) {
1626            String JavaDoc errMsg = "Unable to esablish a connection with the database... Error was: " + e.toString();
1627            Debug.logError(errMsg, module);
1628            if (messages != null) messages.add(errMsg);
1629            return;
1630        }
1631
1632        String JavaDoc message = "Deleting table for entity [" + entity.getEntityName() + "]";
1633        Debug.logImportant(message, module);
1634        if (messages != null) messages.add(message);
1635
1636        StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("DROP TABLE ");
1637        sqlBuf.append(entity.getTableName(datasourceInfo));
1638        if (Debug.verboseOn()) Debug.logVerbose("[deleteTable] sql=" + sqlBuf.toString(), module);
1639        try {
1640            stmt = connection.createStatement();
1641            stmt.executeUpdate(sqlBuf.toString());
1642        } catch (SQLException JavaDoc sqle) {
1643            String JavaDoc errMsg = "SQL Exception while executing the following:\n" + sqlBuf.toString() + "\nError was: " + sqle.toString();
1644            Debug.logError(errMsg, module);
1645            if (messages != null) messages.add(errMsg);
1646        } finally {
1647            try {
1648                if (stmt != null) stmt.close();
1649            } catch (SQLException JavaDoc sqle) {
1650                Debug.logError(sqle, module);
1651            }
1652            try {
1653                if (connection != null) {
1654                    connection.close();
1655                }
1656            } catch (SQLException JavaDoc sqle) {
1657                Debug.logError(sqle, module);
1658            }
1659        }
1660    }
1661
1662    public String JavaDoc addColumn(ModelEntity entity, ModelField field) {
1663        if (entity == null || field == null)
1664            return "ModelEntity or ModelField where null, cannot add column";
1665        if (entity instanceof ModelViewEntity) {
1666            return "ERROR: Cannot add column for a view entity";
1667        }
1668
1669        Connection JavaDoc connection = null;
1670        Statement JavaDoc stmt = null;
1671
1672        try {
1673            connection = getConnection();
1674        } catch (SQLException JavaDoc sqle) {
1675            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
1676        } catch (GenericEntityException e) {
1677            return "Unable to esablish a connection with the database... Error was: " + e.toString();
1678        }
1679
1680        ModelFieldType type = modelFieldTypeReader.getModelFieldType(field.getType());
1681
1682        if (type == null) {
1683            return "Field type [" + type + "] not found for field [" + field.getName() + "] of entity [" + entity.getEntityName() + "], not adding column.";
1684        }
1685
1686        StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("ALTER TABLE ");
1687        sqlBuf.append(entity.getTableName(datasourceInfo));
1688        sqlBuf.append(" ADD ");
1689        sqlBuf.append(field.getColName());
1690        sqlBuf.append(" ");
1691        sqlBuf.append(type.getSqlType());
1692
1693        if("String".equals(type.getJavaType()) || "java.lang.String".equals(type.getJavaType())) {
1694            // if there is a characterSet, add the CHARACTER SET arg here
1695
if (UtilValidate.isNotEmpty(this.datasourceInfo.characterSet)) {
1696                sqlBuf.append(" CHARACTER SET ");
1697                sqlBuf.append(this.datasourceInfo.characterSet);
1698            }
1699
1700            // if there is a collate, add the COLLATE arg here
1701
if (UtilValidate.isNotEmpty(this.datasourceInfo.collate)) {
1702                sqlBuf.append(" COLLATE ");
1703                sqlBuf.append(this.datasourceInfo.collate);
1704            }
1705        }
1706
1707        String JavaDoc sql = sqlBuf.toString();
1708        if (Debug.infoOn()) Debug.logInfo("[addColumn] sql=" + sql, module);
1709        try {
1710            stmt = connection.createStatement();
1711            stmt.executeUpdate(sql);
1712        } catch (SQLException JavaDoc sqle) {
1713            // if that failed try the alternate syntax real quick
1714
StringBuffer JavaDoc sql2Buf = new StringBuffer JavaDoc("ALTER TABLE ");
1715            sql2Buf.append(entity.getTableName(datasourceInfo));
1716            sql2Buf.append(" ADD COLUMN ");
1717            sql2Buf.append(field.getColName());
1718            sql2Buf.append(" ");
1719            sql2Buf.append(type.getSqlType());
1720
1721            if("String".equals(type.getJavaType()) || "java.lang.String".equals(type.getJavaType())) {
1722                // if there is a characterSet, add the CHARACTER SET arg here
1723
if (UtilValidate.isNotEmpty(this.datasourceInfo.characterSet)) {
1724                    sql2Buf.append(" CHARACTER SET ");
1725                    sql2Buf.append(this.datasourceInfo.characterSet);
1726                }
1727
1728                // if there is a collate, add the COLLATE arg here
1729
if (UtilValidate.isNotEmpty(this.datasourceInfo.collate)) {
1730                    sql2Buf.append(" COLLATE ");
1731                    sql2Buf.append(this.datasourceInfo.collate);
1732                }
1733            }
1734
1735            String JavaDoc sql2 = sql2Buf.toString();
1736            if (Debug.infoOn()) Debug.logInfo("[addColumn] sql failed, trying sql2=" + sql2, module);
1737            try {
1738                stmt = connection.createStatement();
1739                stmt.executeUpdate(sql2);
1740            } catch (SQLException JavaDoc sqle2) {
1741                // if this also fails report original error, not this error...
1742
return "SQL Exception while executing the following:\n" + sql + "\nError was: " + sqle.toString();
1743            }
1744        } finally {
1745            try {
1746                if (stmt != null) {
1747                    stmt.close();
1748                }
1749            } catch (SQLException JavaDoc sqle) {
1750                Debug.logError(sqle, module);
1751            }
1752            try {
1753                if (connection != null) {
1754                    connection.close();
1755                }
1756            } catch (SQLException JavaDoc sqle) {
1757                Debug.logError(sqle, module);
1758            }
1759        }
1760        return null;
1761    }
1762
1763    public String JavaDoc renameColumn(ModelEntity entity, ModelField field, String JavaDoc newName) {
1764        if (entity == null || field == null)
1765            return "ModelEntity or ModelField where null, cannot rename column";
1766        if (entity instanceof ModelViewEntity) {
1767            return "ERROR: Cannot rename column for a view entity";
1768        }
1769
1770        Connection JavaDoc connection = null;
1771        Statement JavaDoc stmt = null;
1772
1773        try {
1774            connection = getConnection();
1775        } catch (SQLException JavaDoc sqle) {
1776            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
1777        } catch (GenericEntityException e) {
1778            return "Unable to esablish a connection with the database... Error was: " + e.toString();
1779        }
1780
1781        ModelFieldType type = modelFieldTypeReader.getModelFieldType(field.getType());
1782
1783        if (type == null) {
1784            return "Field type [" + type + "] not found for field [" + field.getName() + "] of entity [" + entity.getEntityName() + "], not renaming column.";
1785        }
1786
1787        StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("ALTER TABLE ");
1788        sqlBuf.append(entity.getTableName(datasourceInfo));
1789        sqlBuf.append(" RENAME ");
1790        sqlBuf.append(field.getColName());
1791        sqlBuf.append(" TO ");
1792        sqlBuf.append(newName);
1793
1794        String JavaDoc sql = sqlBuf.toString();
1795        if (Debug.infoOn()) Debug.logInfo("[renameColumn] sql=" + sql, module);
1796        try {
1797            stmt = connection.createStatement();
1798            stmt.executeUpdate(sql);
1799        } catch (SQLException JavaDoc sqle) {
1800            return "SQL Exception while executing the following:\n" + sql + "\nError was: " + sqle.toString();
1801        } finally {
1802            try {
1803                if (stmt != null) {
1804                    stmt.close();
1805                }
1806            } catch (SQLException JavaDoc sqle) {
1807                Debug.logError(sqle, module);
1808            }
1809            try {
1810                if (connection != null) {
1811                    connection.close();
1812                }
1813            } catch (SQLException JavaDoc sqle) {
1814                Debug.logError(sqle, module);
1815            }
1816        }
1817        return null;
1818    }
1819
1820    public void repairColumnSize(ModelEntity entity, ModelField field, List JavaDoc messages) {
1821        // first rename the column
1822
String JavaDoc tempName = makeTempFieldName(field);
1823        String JavaDoc renamedErr = renameColumn(entity, field, tempName);
1824        if (!UtilValidate.isEmpty(renamedErr)) {
1825            if (messages != null) messages.add(renamedErr);
1826            Debug.logError(renamedErr, module);
1827            return;
1828        }
1829
1830        // next add back in the column
1831
String JavaDoc addedErr = addColumn(entity, field);
1832        if (!UtilValidate.isEmpty(addedErr)) {
1833            if (messages != null) messages.add(addedErr);
1834            Debug.logError(addedErr, module);
1835            return;
1836        }
1837
1838        // need connection
1839
Connection JavaDoc connection = null;
1840        Statement JavaDoc stmt = null;
1841
1842        try {
1843            connection = getConnection();
1844        } catch (SQLException JavaDoc sqle) {
1845            if (messages != null)
1846                messages.add("Unable to esablish a connection with the database... Error was: " + sqle.toString());
1847            return;
1848        } catch (GenericEntityException e) {
1849            if (messages != null)
1850                messages.add("Unable to esablish a connection with the database... Error was: " + e.toString());
1851            return;
1852        }
1853
1854        // copy the data from old to new
1855
StringBuffer JavaDoc sqlBuf1 = new StringBuffer JavaDoc("UPDATE ");
1856        sqlBuf1.append(entity.getTableName(datasourceInfo));
1857        sqlBuf1.append(" SET ");
1858        sqlBuf1.append(field.getColName());
1859        sqlBuf1.append(" = ");
1860        sqlBuf1.append(tempName);
1861
1862        String JavaDoc sql1 = sqlBuf1.toString();
1863        if (Debug.infoOn()) Debug.logInfo("[moveData] sql=" + sql1, module);
1864        try {
1865            stmt = connection.createStatement();
1866            int changed = stmt.executeUpdate(sql1);
1867            if (Debug.infoOn()) Debug.logInfo("[moveData] " + changed + " records updated", module);
1868        } catch (SQLException JavaDoc sqle) {
1869            String JavaDoc thisMsg = "SQL Exception while executing the following:\n" + sql1 + "\nError was: " + sqle.toString();
1870            if (messages != null)
1871                messages.add(thisMsg);
1872            Debug.logError(thisMsg, module);
1873            return;
1874        } finally {
1875            try {
1876                if (stmt != null) {
1877                    stmt.close();
1878                }
1879            } catch (SQLException JavaDoc sqle) {
1880                Debug.logError(sqle, module);
1881            }
1882            try {
1883                if (connection != null) {
1884                    connection.close();
1885                }
1886            } catch (SQLException JavaDoc sqle) {
1887                Debug.logError(sqle, module);
1888            }
1889        }
1890
1891        // fresh connection
1892
try {
1893            connection = getConnection();
1894        } catch (SQLException JavaDoc sqle) {
1895            if (messages != null)
1896                messages.add("Unable to esablish a connection with the database... Error was: " + sqle.toString());
1897            return;
1898        } catch (GenericEntityException e) {
1899            if (messages != null)
1900                messages.add("Unable to esablish a connection with the database... Error was: " + e.toString());
1901            return;
1902        }
1903
1904        // remove the old column
1905
StringBuffer JavaDoc sqlBuf2 = new StringBuffer JavaDoc("ALTER TABLE ");
1906        sqlBuf2.append(entity.getTableName(datasourceInfo));
1907        sqlBuf2.append(" DROP COLUMN ");
1908        sqlBuf2.append(tempName);
1909
1910        String JavaDoc sql2 = sqlBuf2.toString();
1911        if (Debug.infoOn()) Debug.logInfo("[dropColumn] sql=" + sql2, module);
1912        try {
1913            stmt = connection.createStatement();
1914            stmt.executeUpdate(sql2);
1915        } catch (SQLException JavaDoc sqle) {
1916            String JavaDoc thisMsg = "SQL Exception while executing the following:\n" + sql2 + "\nError was: " + sqle.toString();
1917            if (messages != null)
1918                messages.add(thisMsg);
1919            Debug.logError(thisMsg, module);
1920            return;
1921        } finally {
1922            try {
1923                if (stmt != null) {
1924                    stmt.close();
1925                }
1926            } catch (SQLException JavaDoc sqle) {
1927                Debug.logError(sqle, module);
1928            }
1929            try {
1930                if (connection != null) {
1931                    connection.close();
1932                }
1933            } catch (SQLException JavaDoc sqle) {
1934                Debug.logError(sqle, module);
1935            }
1936        }
1937    }
1938
1939    public void repairColumnSizeChanges(Map JavaDoc modelEntities, List JavaDoc fieldsWrongSize, List JavaDoc messages) {
1940        if (modelEntities == null || fieldsWrongSize == null || fieldsWrongSize.size() == 0) {
1941            messages.add("No fields to repair");
1942            return;
1943        }
1944
1945        if (messages == null) messages = new ArrayList JavaDoc();
1946
1947        Iterator JavaDoc i = fieldsWrongSize.iterator();
1948        while (i.hasNext()) {
1949            String JavaDoc fieldInfo = (String JavaDoc) i.next();
1950            String JavaDoc entityName = fieldInfo.substring(0, fieldInfo.indexOf('.'));
1951            String JavaDoc fieldName = fieldInfo.substring(fieldInfo.indexOf('.') + 1);
1952
1953            ModelEntity modelEntity = (ModelEntity) modelEntities.get(entityName);
1954            ModelField modelField = modelEntity.getField(fieldName);
1955            repairColumnSize(modelEntity, modelField, messages);
1956        }
1957    }
1958
1959    private String JavaDoc makeTempFieldName(ModelField field) {
1960        String JavaDoc tempName = "tmp_" + field.getName();
1961        if (tempName.length() > 30) {
1962            tempName = tempName.substring(0, 30);
1963        }
1964        return tempName.toUpperCase();
1965    }
1966
1967    /* ====================================================================== */
1968
1969    /* ====================================================================== */
1970    public String JavaDoc makePkConstraintName(ModelEntity entity, int constraintNameClipLength) {
1971        String JavaDoc pkName = "PK_" + entity.getPlainTableName();
1972
1973        if (pkName.length() > constraintNameClipLength) {
1974            pkName = pkName.substring(0, constraintNameClipLength);
1975        }
1976
1977        return pkName;
1978    }
1979
1980    public String JavaDoc makeFkConstraintName(ModelRelation modelRelation, int constraintNameClipLength) {
1981        String JavaDoc relConstraintName = modelRelation.getFkName();
1982
1983        if (relConstraintName == null || relConstraintName.length() == 0) {
1984            relConstraintName = modelRelation.getTitle() + modelRelation.getRelEntityName();
1985            relConstraintName = relConstraintName.toUpperCase();
1986        }
1987
1988        if (relConstraintName.length() > constraintNameClipLength) {
1989            relConstraintName = relConstraintName.substring(0, constraintNameClipLength);
1990        }
1991
1992        return relConstraintName;
1993    }
1994
1995    /* ====================================================================== */
1996    public String JavaDoc makeIndexName(ModelIndex modelIndex, int constraintNameClipLength) {
1997        String JavaDoc indexName = modelIndex.getName();
1998
1999        if (indexName.length() > constraintNameClipLength) {
2000            indexName = indexName.substring(0, constraintNameClipLength);
2001        }
2002
2003        return indexName;
2004    }
2005
2006    /* ====================================================================== */
2007    public int createForeignKeys(ModelEntity entity, Map JavaDoc modelEntities, List JavaDoc messages) {
2008        return this.createForeignKeys(entity, modelEntities, datasourceInfo.constraintNameClipLength, datasourceInfo.fkStyle, datasourceInfo.useFkInitiallyDeferred, messages);
2009    }
2010    public int createForeignKeys(ModelEntity entity, Map JavaDoc modelEntities, int constraintNameClipLength, String JavaDoc fkStyle, boolean useFkInitiallyDeferred, List JavaDoc messages) {
2011        if (entity == null) {
2012            String JavaDoc errMsg = "ModelEntity was null and is required to create foreign keys for a table";
2013            Debug.logError(errMsg, module);
2014            if (messages != null) messages.add(errMsg);
2015            return 0;
2016        }
2017        if (entity instanceof ModelViewEntity) {
2018            //String errMsg = "ERROR: Cannot create foreign keys for a view entity";
2019
//Debug.logError(errMsg, module);
2020
//if (messages != null) messages.add(errMsg);
2021
return 0;
2022        }
2023
2024        int fksCreated = 0;
2025
2026        // go through the relationships to see if any foreign keys need to be added
2027
Iterator JavaDoc relationsIter = entity.getRelationsIterator();
2028        while (relationsIter.hasNext()) {
2029            ModelRelation modelRelation = (ModelRelation) relationsIter.next();
2030            if ("one".equals(modelRelation.getType())) {
2031                ModelEntity relModelEntity = (ModelEntity) modelEntities.get(modelRelation.getRelEntityName());
2032
2033                if (relModelEntity == null) {
2034                    String JavaDoc errMsg = "Error adding foreign key: ModelEntity was null for related entity name " + modelRelation.getRelEntityName();
2035                    Debug.logError(errMsg, module);
2036                    if (messages != null) messages.add(errMsg);
2037                    continue;
2038                }
2039                if (relModelEntity instanceof ModelViewEntity) {
2040                    String JavaDoc errMsg = "Error adding foreign key: related entity is a view entity for related entity name " + modelRelation.getRelEntityName();
2041                    Debug.logError(errMsg, module);
2042                    if (messages != null) messages.add(errMsg);
2043                    continue;
2044                }
2045
2046                String JavaDoc retMsg = createForeignKey(entity, modelRelation, relModelEntity, constraintNameClipLength, fkStyle, useFkInitiallyDeferred);
2047                if (retMsg != null && retMsg.length() > 0) {
2048                    Debug.logError(retMsg, module);
2049                    if (messages != null) messages.add(retMsg);
2050                    continue;
2051                }
2052
2053                fksCreated++;
2054            }
2055        }
2056
2057        if (fksCreated > 0) {
2058            String JavaDoc message = "Created " + fksCreated + " foreign keys for entity [" + entity.getEntityName() + "]";
2059            Debug.logImportant(message, module);
2060            if (messages != null) messages.add(message);
2061        }
2062
2063        return fksCreated;
2064    }
2065
2066    public String JavaDoc createForeignKey(ModelEntity entity, ModelRelation modelRelation, ModelEntity relModelEntity, int constraintNameClipLength, String JavaDoc fkStyle, boolean useFkInitiallyDeferred) {
2067        Connection JavaDoc connection = null;
2068        Statement JavaDoc stmt = null;
2069
2070        try {
2071            connection = getConnection();
2072        } catch (SQLException JavaDoc sqle) {
2073            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
2074        } catch (GenericEntityException e) {
2075            return "Unable to esablish a connection with the database... Error was: " + e.toString();
2076        }
2077
2078        // now add constraint clause
2079
StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("ALTER TABLE ");
2080        sqlBuf.append(entity.getTableName(datasourceInfo));
2081        sqlBuf.append(" ADD ");
2082        String JavaDoc fkConstraintClause = makeFkConstraintClause(entity, modelRelation, relModelEntity, constraintNameClipLength, fkStyle, useFkInitiallyDeferred);
2083        if (UtilValidate.isEmpty(fkConstraintClause)) {
2084            return "Error creating foreign key constraint clause, see log for details";
2085        }
2086        sqlBuf.append(fkConstraintClause);
2087
2088        if (Debug.verboseOn()) Debug.logVerbose("[createForeignKey] sql=" + sqlBuf.toString(), module);
2089        try {
2090            stmt = connection.createStatement();
2091            stmt.executeUpdate(sqlBuf.toString());
2092        } catch (SQLException JavaDoc sqle) {
2093            return "SQL Exception while executing the following:\n" + sqlBuf.toString() + "\nError was: " + sqle.toString();
2094        } finally {
2095            try {
2096                if (stmt != null) {
2097                    stmt.close();
2098                }
2099            } catch (SQLException JavaDoc sqle) {
2100                Debug.logError(sqle, module);
2101            }
2102            try {
2103                if (connection != null) {
2104                    connection.close();
2105                }
2106            } catch (SQLException JavaDoc sqle) {
2107                Debug.logError(sqle, module);
2108            }
2109        }
2110        return null;
2111    }
2112
2113    public String JavaDoc makeFkConstraintClause(ModelEntity entity, ModelRelation modelRelation, ModelEntity relModelEntity, int constraintNameClipLength, String JavaDoc fkStyle, boolean useFkInitiallyDeferred) {
2114        // make the two column lists
2115
Iterator JavaDoc keyMapsIter = modelRelation.getKeyMapsIterator();
2116        StringBuffer JavaDoc mainCols = new StringBuffer JavaDoc();
2117        StringBuffer JavaDoc relCols = new StringBuffer JavaDoc();
2118
2119        while (keyMapsIter.hasNext()) {
2120            ModelKeyMap keyMap = (ModelKeyMap) keyMapsIter.next();
2121
2122            ModelField mainField = entity.getField(keyMap.getFieldName());
2123            if (mainField == null) {
2124                Debug.logError("Bad key-map in entity [" + entity.getEntityName() + "] relation to [" + modelRelation.getTitle() + modelRelation.getRelEntityName() + "] for field [" + keyMap.getFieldName() + "]", module);
2125                return null;
2126            }
2127
2128            if (mainCols.length() > 0) {
2129                mainCols.append(", ");
2130            }
2131            mainCols.append(mainField.getColName());
2132
2133            ModelField relField = relModelEntity.getField(keyMap.getRelFieldName());
2134
2135            if (relCols.length() > 0) {
2136                relCols.append(", ");
2137            }
2138            relCols.append(relField.getColName());
2139        }
2140
2141        StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("");
2142
2143        if ("name_constraint".equals(fkStyle)) {
2144            sqlBuf.append("CONSTRAINT ");
2145            String JavaDoc relConstraintName = makeFkConstraintName(modelRelation, constraintNameClipLength);
2146
2147            sqlBuf.append(relConstraintName);
2148
2149            sqlBuf.append(" FOREIGN KEY (");
2150            sqlBuf.append(mainCols.toString());
2151            sqlBuf.append(") REFERENCES ");
2152            sqlBuf.append(relModelEntity.getTableName(datasourceInfo));
2153            sqlBuf.append(" (");
2154            sqlBuf.append(relCols.toString());
2155            sqlBuf.append(")");
2156            if (useFkInitiallyDeferred) {
2157                sqlBuf.append(" INITIALLY DEFERRED");
2158            }
2159        } else if ("name_fk".equals(fkStyle)) {
2160            sqlBuf.append(" FOREIGN KEY ");
2161            String JavaDoc relConstraintName = makeFkConstraintName(modelRelation, constraintNameClipLength);
2162
2163            sqlBuf.append(relConstraintName);
2164            sqlBuf.append(" (");
2165            sqlBuf.append(mainCols.toString());
2166            sqlBuf.append(") REFERENCES ");
2167            sqlBuf.append(relModelEntity.getTableName(datasourceInfo));
2168            sqlBuf.append(" (");
2169            sqlBuf.append(relCols.toString());
2170            sqlBuf.append(")");
2171            if (useFkInitiallyDeferred) {
2172                sqlBuf.append(" INITIALLY DEFERRED");
2173            }
2174        } else {
2175            String JavaDoc emsg = "ERROR: fk-style specified for this data-source is not valid: " + fkStyle;
2176
2177            Debug.logError(emsg, module);
2178            throw new IllegalArgumentException JavaDoc(emsg);
2179        }
2180
2181        return sqlBuf.toString();
2182    }
2183
2184    public void deleteForeignKeys(ModelEntity entity, Map JavaDoc modelEntities, List JavaDoc messages) {
2185        this.deleteForeignKeys(entity, modelEntities, datasourceInfo.constraintNameClipLength, messages);
2186    }
2187
2188    public void deleteForeignKeys(ModelEntity entity, Map JavaDoc modelEntities, int constraintNameClipLength, List JavaDoc messages) {
2189        if (entity == null) {
2190            String JavaDoc errMsg = "ModelEntity was null and is required to delete foreign keys for a table";
2191            if (messages != null) messages.add(errMsg);
2192            Debug.logError(errMsg, module);
2193            return;
2194        }
2195        if (entity instanceof ModelViewEntity) {
2196            //String errMsg = "ERROR: Cannot delete foreign keys for a view entity";
2197
//if (messages != null) messages.add(errMsg);
2198
//Debug.logError(errMsg, module);
2199
return;
2200        }
2201
2202        String JavaDoc message = "Deleting foreign keys for entity [" + entity.getEntityName() + "]";
2203        Debug.logImportant(message, module);
2204        if (messages != null) messages.add(message);
2205
2206        // go through the relationships to see if any foreign keys need to be added
2207
Iterator JavaDoc relationsIter = entity.getRelationsIterator();
2208        while (relationsIter.hasNext()) {
2209            ModelRelation modelRelation = (ModelRelation) relationsIter.next();
2210
2211            if ("one".equals(modelRelation.getType())) {
2212                ModelEntity relModelEntity = (ModelEntity) modelEntities.get(modelRelation.getRelEntityName());
2213
2214                if (relModelEntity == null) {
2215                    String JavaDoc errMsg = "Error removing foreign key: ModelEntity was null for related entity name " + modelRelation.getRelEntityName();
2216                    if (messages != null) messages.add(errMsg);
2217                    Debug.logError(errMsg, module);
2218                    continue;
2219                }
2220                if (relModelEntity instanceof ModelViewEntity) {
2221                    String JavaDoc errMsg = "Error removing foreign key: related entity is a view entity for related entity name " + modelRelation.getRelEntityName();
2222                    if (messages != null) messages.add(errMsg);
2223                    Debug.logError(errMsg, module);
2224                    continue;
2225                }
2226
2227                String JavaDoc retMsg = deleteForeignKey(entity, modelRelation, relModelEntity, constraintNameClipLength);
2228                if (retMsg != null && retMsg.length() > 0) {
2229                    if (messages != null) messages.add(retMsg);
2230                    Debug.logError(retMsg, module);
2231                }
2232            }
2233        }
2234    }
2235
2236    public String JavaDoc deleteForeignKey(ModelEntity entity, ModelRelation modelRelation, ModelEntity relModelEntity, int constraintNameClipLength) {
2237        Connection JavaDoc connection = null;
2238        Statement JavaDoc stmt = null;
2239
2240        try {
2241            connection = getConnection();
2242        } catch (SQLException JavaDoc sqle) {
2243            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
2244        } catch (GenericEntityException e) {
2245            return "Unable to esablish a connection with the database... Error was: " + e.toString();
2246        }
2247
2248        String JavaDoc relConstraintName = makeFkConstraintName(modelRelation, constraintNameClipLength);
2249
2250        // now add constraint clause
2251
StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("ALTER TABLE ");
2252        sqlBuf.append(entity.getTableName(datasourceInfo));
2253        if (datasourceInfo.dropFkUseForeignKeyKeyword) {
2254            sqlBuf.append(" DROP FOREIGN KEY ");
2255        } else {
2256            sqlBuf.append(" DROP CONSTRAINT ");
2257        }
2258        sqlBuf.append(relConstraintName);
2259
2260        if (Debug.verboseOn()) Debug.logVerbose("[deleteForeignKey] sql=" + sqlBuf.toString(), module);
2261        try {
2262            stmt = connection.createStatement();
2263            stmt.executeUpdate(sqlBuf.toString());
2264        } catch (SQLException JavaDoc sqle) {
2265            return "SQL Exception while executing the following:\n" + sqlBuf.toString() + "\nError was: " + sqle.toString();
2266        } finally {
2267            try {
2268                if (stmt != null)
2269                    stmt.close();
2270            } catch (SQLException JavaDoc sqle) {
2271                Debug.logError(sqle, module);
2272            }
2273            try {
2274                if (connection != null) {
2275                    connection.close();
2276                }
2277            } catch (SQLException JavaDoc sqle) {
2278                Debug.logError(sqle, module);
2279            }
2280        }
2281        return null;
2282    }
2283
2284    /* ====================================================================== */
2285    /* ====================================================================== */
2286    public void createPrimaryKey(ModelEntity entity, boolean usePkConstraintNames, int constraintNameClipLength, List JavaDoc messages) {
2287        if (messages == null) messages = new ArrayList JavaDoc();
2288        String JavaDoc err = createPrimaryKey(entity, usePkConstraintNames, constraintNameClipLength);
2289        if (!UtilValidate.isEmpty(err)) {
2290            messages.add(err);
2291        }
2292    }
2293
2294    public void createPrimaryKey(ModelEntity entity, boolean usePkConstraintNames, List JavaDoc messages) {
2295        createPrimaryKey(entity, usePkConstraintNames, datasourceInfo.constraintNameClipLength, messages);
2296    }
2297
2298    public void createPrimaryKey(ModelEntity entity, List JavaDoc messages) {
2299        createPrimaryKey(entity, datasourceInfo.usePkConstraintNames, messages);
2300    }
2301
2302    public String JavaDoc createPrimaryKey(ModelEntity entity, boolean usePkConstraintNames, int constraintNameClipLength) {
2303        if (entity == null) {
2304            return "ModelEntity was null and is required to create the primary key for a table";
2305        }
2306        if (entity instanceof ModelViewEntity) {
2307            return "Ignoring view entity [" + entity.getEntityName() + "]";
2308        }
2309
2310        String JavaDoc message;
2311        if (entity.getPksSize() > 0) {
2312            message = "Creating primary key for entity [" + entity.getEntityName() + "]";
2313            Connection JavaDoc connection = null;
2314            Statement JavaDoc stmt = null;
2315
2316            try {
2317                connection = getConnection();
2318            } catch (SQLException JavaDoc sqle) {
2319                return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
2320            } catch (GenericEntityException e) {
2321                return "Unable to esablish a connection with the database... Error was: " + e.toString();
2322            }
2323
2324            // now add constraint clause
2325
StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("ALTER TABLE ");
2326            sqlBuf.append(entity.getTableName(datasourceInfo));
2327            sqlBuf.append(" ADD ");
2328
2329            String JavaDoc pkName = makePkConstraintName(entity, constraintNameClipLength);
2330
2331            if (usePkConstraintNames) {
2332                sqlBuf.append("CONSTRAINT ");
2333                sqlBuf.append(pkName);
2334            }
2335            sqlBuf.append(" PRIMARY KEY (");
2336            sqlBuf.append(entity.colNameString(entity.getPksCopy()));
2337            sqlBuf.append(")");
2338
2339            if (Debug.verboseOn()) Debug.logVerbose("[createPrimaryKey] sql=" + sqlBuf.toString(), module);
2340            try {
2341                stmt = connection.createStatement();
2342                stmt.executeUpdate(sqlBuf.toString());
2343            } catch (SQLException JavaDoc sqle) {
2344                return "SQL Exception while executing the following:\n" + sqlBuf.toString() + "\nError was: " + sqle.toString();
2345            } finally {
2346                try {
2347                    if (stmt != null) {
2348                        stmt.close();
2349                    }
2350                } catch (SQLException JavaDoc sqle) {
2351                    Debug.logError(sqle, module);
2352                }
2353                try {
2354                    if (connection != null) {
2355                        connection.close();
2356                    }
2357                } catch (SQLException JavaDoc sqle) {
2358                    Debug.logError(sqle, module);
2359                }
2360            }
2361        } else {
2362            message = "No primary-key defined for table [" + entity.getEntityName() + "]";
2363        }
2364
2365        Debug.logImportant(message, module);
2366        return message;
2367    }
2368
2369    public void deletePrimaryKey(ModelEntity entity, boolean usePkConstraintNames, int constraintNameClipLength, List JavaDoc messages) {
2370        if (messages == null) messages = new ArrayList JavaDoc();
2371        String JavaDoc err = deletePrimaryKey(entity, usePkConstraintNames, constraintNameClipLength);
2372        if (!UtilValidate.isEmpty(err)) {
2373            messages.add(err);
2374        }
2375    }
2376
2377    public void deletePrimaryKey(ModelEntity entity, boolean usePkConstraintNames, List JavaDoc messages) {
2378        deletePrimaryKey(entity, usePkConstraintNames, datasourceInfo.constraintNameClipLength, messages);
2379    }
2380
2381    public void deletePrimaryKey(ModelEntity entity, List JavaDoc messages) {
2382        deletePrimaryKey(entity, datasourceInfo.usePkConstraintNames, messages);
2383    }
2384
2385    public String JavaDoc deletePrimaryKey(ModelEntity entity, boolean usePkConstraintNames, int constraintNameClipLength) {
2386        if (entity == null) {
2387            return "ModelEntity was null and is required to delete the primary key for a table";
2388        }
2389        if (entity instanceof ModelViewEntity) {
2390            return "Ignoring view entity [" + entity.getEntityName() + "]";
2391        }
2392
2393        String JavaDoc message;
2394        if (entity.getPksSize() > 0) {
2395            message = "Deleting primary key for entity [" + entity.getEntityName() + "]";
2396            Connection JavaDoc connection = null;
2397            Statement JavaDoc stmt = null;
2398            try {
2399                connection = getConnection();
2400            } catch (SQLException JavaDoc sqle) {
2401                return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
2402            } catch (GenericEntityException e) {
2403                return "Unable to esablish a connection with the database... Error was: " + e.toString();
2404            }
2405
2406            // now add constraint clause
2407
StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("ALTER TABLE ");
2408            sqlBuf.append(entity.getTableName(datasourceInfo));
2409            sqlBuf.append(" DROP ");
2410
2411            String JavaDoc pkName = makePkConstraintName(entity, constraintNameClipLength);
2412
2413            if (usePkConstraintNames) {
2414                sqlBuf.append("CONSTRAINT ");
2415                sqlBuf.append(pkName);
2416                sqlBuf.append(" CASCADE");
2417            } else {
2418                sqlBuf.append(" PRIMARY KEY");
2419                // DEJ20050502 not sure why this is here, shouldn't be needed and some dbs don't support like this, ie when used with PRIMARY KEY: sqlBuf.append(" CASCADE");
2420
}
2421
2422            if (Debug.verboseOn()) Debug.logVerbose("[deletePrimaryKey] sql=" + sqlBuf.toString(), module);
2423            try {
2424                stmt = connection.createStatement();
2425                stmt.executeUpdate(sqlBuf.toString());
2426            } catch (SQLException JavaDoc sqle) {
2427                return "SQL Exception while executing the following:\n" + sqlBuf.toString() + "\nError was: " + sqle.toString();
2428            } finally {
2429                try {
2430                    if (stmt != null)
2431                        stmt.close();
2432                } catch (SQLException JavaDoc sqle) {
2433                    Debug.logError(sqle, module);
2434                }
2435                try {
2436                    if (connection != null) {
2437                        connection.close();
2438                    }
2439                } catch (SQLException JavaDoc sqle) {
2440                    Debug.logError(sqle, module);
2441                }
2442            }
2443        } else {
2444            message = "No primary-key defined for table [" + entity.getEntityName() + "]";
2445        }
2446
2447        Debug.logImportant(message, module);
2448        return message;
2449    }
2450
2451    /* ====================================================================== */
2452    /* ====================================================================== */
2453    public int createDeclaredIndices(ModelEntity entity, List JavaDoc messages) {
2454        if (entity == null) {
2455            String JavaDoc message = "ERROR: ModelEntity was null and is required to create declared indices for a table";
2456            Debug.logError(message, module);
2457            if (messages != null) messages.add(message);
2458            return 0;
2459        }
2460        if (entity instanceof ModelViewEntity) {
2461            String JavaDoc message = "WARNING: Cannot create declared indices for a view entity";
2462            Debug.logWarning(message, module);
2463            if (messages != null) messages.add(message);
2464            return 0;
2465        }
2466
2467        int dinsCreated = 0;
2468
2469        // go through the indexes to see if any need to be added
2470
Iterator JavaDoc indexesIter = entity.getIndexesIterator();
2471        while (indexesIter.hasNext()) {
2472            ModelIndex modelIndex = (ModelIndex) indexesIter.next();
2473
2474            String JavaDoc retMsg = createDeclaredIndex(entity, modelIndex);
2475            if (retMsg != null && retMsg.length() > 0) {
2476                String JavaDoc message = "Could not create declared indices for entity [" + entity.getEntityName() + "]: " + retMsg;
2477                Debug.logError(message, module);
2478                if (messages != null) messages.add(message);
2479                continue;
2480            }
2481            dinsCreated++;
2482        }
2483
2484        if (dinsCreated > 0) {
2485            String JavaDoc message = "Created " + dinsCreated + " declared indices for entity [" + entity.getEntityName() + "]";
2486            Debug.logImportant(message, module);
2487            if (messages != null) messages.add(message);
2488        }
2489        return dinsCreated;
2490    }
2491
2492    public String JavaDoc createDeclaredIndex(ModelEntity entity, ModelIndex modelIndex) {
2493        Connection JavaDoc connection = null;
2494        Statement JavaDoc stmt = null;
2495
2496        try {
2497            connection = getConnection();
2498        } catch (SQLException JavaDoc sqle) {
2499            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
2500        } catch (GenericEntityException e) {
2501            return "Unable to esablish a connection with the database... Error was: " + e.toString();
2502        }
2503
2504        String JavaDoc createIndexSql = makeIndexClause(entity, modelIndex);
2505        if (Debug.verboseOn()) Debug.logVerbose("[createForeignKeyIndex] index sql=" + createIndexSql, module);
2506
2507        try {
2508            stmt = connection.createStatement();
2509            stmt.executeUpdate(createIndexSql);
2510        } catch (SQLException JavaDoc sqle) {
2511            return "SQL Exception while executing the following:\n" + createIndexSql + "\nError was: " + sqle.toString();
2512        } finally {
2513            try {
2514                if (stmt != null) stmt.close();
2515            } catch (SQLException JavaDoc sqle) {
2516                Debug.logError(sqle, module);
2517            }
2518            try {
2519                if (connection != null) {
2520                    connection.close();
2521                }
2522            } catch (SQLException JavaDoc sqle) {
2523                Debug.logError(sqle, module);
2524            }
2525        }
2526        return null;
2527    }
2528
2529    public String JavaDoc makeIndexClause(ModelEntity entity, ModelIndex modelIndex) {
2530        Iterator JavaDoc fieldNamesIter = modelIndex.getIndexFieldsIterator();
2531        StringBuffer JavaDoc mainCols = new StringBuffer JavaDoc();
2532
2533        while (fieldNamesIter.hasNext()) {
2534            String JavaDoc fieldName = (String JavaDoc) fieldNamesIter.next();
2535            ModelField mainField = entity.getField(fieldName);
2536            if (mainCols.length() > 0) {
2537                mainCols.append(", ");
2538            }
2539            mainCols.append(mainField.getColName());
2540        }
2541
2542        StringBuffer JavaDoc indexSqlBuf = new StringBuffer JavaDoc("CREATE ");
2543        if (modelIndex.getUnique()) {
2544            indexSqlBuf.append("UNIQUE ");
2545        }
2546        indexSqlBuf.append("INDEX ");
2547        indexSqlBuf.append(makeIndexName(modelIndex, datasourceInfo.constraintNameClipLength));
2548        indexSqlBuf.append(" ON ");
2549        indexSqlBuf.append(entity.getTableName(datasourceInfo));
2550
2551        indexSqlBuf.append(" (");
2552        indexSqlBuf.append(mainCols.toString());
2553        indexSqlBuf.append(")");
2554
2555        return indexSqlBuf.toString();
2556    }
2557
2558    public void deleteDeclaredIndices(ModelEntity entity, List JavaDoc messages) {
2559        if (messages == null) messages = new ArrayList JavaDoc();
2560        String JavaDoc err = deleteDeclaredIndices(entity);
2561        if (!UtilValidate.isEmpty(err)) {
2562            messages.add(err);
2563        }
2564    }
2565
2566    public String JavaDoc deleteDeclaredIndices(ModelEntity entity) {
2567        if (entity == null) {
2568            return "ModelEntity was null and is required to delete declared indices for a table";
2569        }
2570        if (entity instanceof ModelViewEntity) {
2571            return "ERROR: Cannot delete declared indices for a view entity";
2572        }
2573
2574        StringBuffer JavaDoc retMsgsBuffer = new StringBuffer JavaDoc();
2575
2576        // go through the relationships to see if any foreign keys need to be added
2577
Iterator JavaDoc indexesIter = entity.getIndexesIterator();
2578        while (indexesIter.hasNext()) {
2579            ModelIndex modelIndex = (ModelIndex) indexesIter.next();
2580            String JavaDoc retMsg = deleteDeclaredIndex(entity, modelIndex);
2581            if (retMsg != null && retMsg.length() > 0) {
2582                if (retMsgsBuffer.length() > 0) {
2583                    retMsgsBuffer.append("\n");
2584                }
2585                retMsgsBuffer.append(retMsg);
2586                if (Debug.infoOn()) Debug.logInfo(retMsg, module);
2587            }
2588        }
2589
2590        if (retMsgsBuffer.length() > 0) {
2591            return retMsgsBuffer.toString();
2592        } else {
2593            return null;
2594        }
2595    }
2596
2597    public String JavaDoc deleteDeclaredIndex(ModelEntity entity, ModelIndex modelIndex) {
2598        Connection JavaDoc connection = null;
2599        Statement JavaDoc stmt = null;
2600
2601        try {
2602            connection = getConnection();
2603        } catch (SQLException JavaDoc sqle) {
2604            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
2605        } catch (GenericEntityException e) {
2606            return "Unable to esablish a connection with the database... Error was: " + e.toString();
2607        }
2608
2609        // TODO: also remove the constraing if this was a unique index, in most databases dropping the index does not drop the constraint
2610

2611        StringBuffer JavaDoc indexSqlBuf = new StringBuffer JavaDoc("DROP INDEX ");
2612        String JavaDoc tableName = entity.getTableName(datasourceInfo);
2613        String JavaDoc schemaName = (tableName == null || tableName.length() == 0 || tableName.indexOf('.') == -1) ? "" :
2614                tableName.substring(0, tableName.indexOf('.'));
2615
2616        indexSqlBuf.append(schemaName);
2617        indexSqlBuf.append(".");
2618        indexSqlBuf.append(modelIndex.getName());
2619
2620        String JavaDoc deleteIndexSql = indexSqlBuf.toString();
2621        if (Debug.verboseOn()) Debug.logVerbose("[deleteDeclaredIndex] index sql=" + deleteIndexSql, module);
2622
2623        try {
2624            stmt = connection.createStatement();
2625            stmt.executeUpdate(deleteIndexSql);
2626        } catch (SQLException JavaDoc sqle) {
2627            return "SQL Exception while executing the following:\n" + deleteIndexSql + "\nError was: " + sqle.toString();
2628        } finally {
2629            try {
2630                if (stmt != null) stmt.close();
2631            } catch (SQLException JavaDoc sqle) {
2632                Debug.logError(sqle, module);
2633            }
2634            try {
2635                if (connection != null) {
2636                    connection.close();
2637                }
2638            } catch (SQLException JavaDoc sqle) {
2639                Debug.logError(sqle, module);
2640            }
2641        }
2642        return null;
2643    }
2644
2645    /* ====================================================================== */
2646    /* ====================================================================== */
2647    public int createForeignKeyIndices(ModelEntity entity, List JavaDoc messages) {
2648        return createForeignKeyIndices(entity, datasourceInfo.constraintNameClipLength, messages);
2649    }
2650
2651    public int createForeignKeyIndices(ModelEntity entity, int constraintNameClipLength, List JavaDoc messages) {
2652        if (entity == null) {
2653            String JavaDoc message = "ERROR: ModelEntity was null and is required to create foreign keys indices for a table";
2654            Debug.logError(message, module);
2655            if (messages != null) messages.add(message);
2656            return 0;
2657        }
2658        if (entity instanceof ModelViewEntity) {
2659            String JavaDoc message = "WARNING: Cannot create foreign keys indices for a view entity";
2660            Debug.logWarning(message, module);
2661            if (messages != null) messages.add(message);
2662            return 0;
2663        }
2664
2665        int fkisCreated = 0;
2666
2667        // go through the relationships to see if any foreign keys need to be added
2668
Iterator JavaDoc relationsIter = entity.getRelationsIterator();
2669        while (relationsIter.hasNext()) {
2670            ModelRelation modelRelation = (ModelRelation) relationsIter.next();
2671            if ("one".equals(modelRelation.getType())) {
2672                String JavaDoc retMsg = createForeignKeyIndex(entity, modelRelation, constraintNameClipLength);
2673                if (retMsg != null && retMsg.length() > 0) {
2674                    String JavaDoc message = "Could not create foreign key indices for entity [" + entity.getEntityName() + "]: " + retMsg;
2675                    Debug.logError(message, module);
2676                    if (messages != null) messages.add(message);
2677                    continue;
2678                }
2679                fkisCreated++;
2680            }
2681        }
2682
2683        if (fkisCreated > 0) {
2684            String JavaDoc message = "Created " + fkisCreated + " foreign key indices for entity [" + entity.getEntityName() + "]";
2685            Debug.logImportant(message, module);
2686            if (messages != null) messages.add(message);
2687        }
2688        return fkisCreated;
2689    }
2690
2691    public String JavaDoc createForeignKeyIndex(ModelEntity entity, ModelRelation modelRelation, int constraintNameClipLength) {
2692        Connection JavaDoc connection = null;
2693        Statement JavaDoc stmt = null;
2694
2695        try {
2696            connection = getConnection();
2697        } catch (SQLException JavaDoc sqle) {
2698            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
2699        } catch (GenericEntityException e) {
2700            return "Unable to esablish a connection with the database... Error was: " + e.toString();
2701        }
2702
2703        String JavaDoc createIndexSql = makeFkIndexClause(entity, modelRelation, constraintNameClipLength);
2704        if (UtilValidate.isEmpty(createIndexSql)) {
2705            return "Error creating foreign key index clause, see log for details";
2706        }
2707
2708        if (Debug.verboseOn()) Debug.logVerbose("[createForeignKeyIndex] index sql=" + createIndexSql, module);
2709
2710        try {
2711            stmt = connection.createStatement();
2712            stmt.executeUpdate(createIndexSql);
2713        } catch (SQLException JavaDoc sqle) {
2714            return "SQL Exception while executing the following:\n" + createIndexSql + "\nError was: " + sqle.toString();
2715        } finally {
2716            try {
2717                if (stmt != null)
2718                    stmt.close();
2719            } catch (SQLException JavaDoc sqle) {
2720                Debug.logError(sqle, module);
2721            }
2722            try {
2723                if (connection != null) {
2724                    connection.close();
2725                }
2726            } catch (SQLException JavaDoc sqle) {
2727                Debug.logError(sqle, module);
2728            }
2729        }
2730        return null;
2731    }
2732
2733    public String JavaDoc makeFkIndexClause(ModelEntity entity, ModelRelation modelRelation, int constraintNameClipLength) {
2734        Iterator JavaDoc keyMapsIter = modelRelation.getKeyMapsIterator();
2735        StringBuffer JavaDoc mainCols = new StringBuffer JavaDoc();
2736
2737        while (keyMapsIter.hasNext()) {
2738            ModelKeyMap keyMap = (ModelKeyMap) keyMapsIter.next();
2739            ModelField mainField = entity.getField(keyMap.getFieldName());
2740
2741            if (mainField == null) {
2742                Debug.logError("Bad key-map in entity [" + entity.getEntityName() + "] relation to [" + modelRelation.getTitle() + modelRelation.getRelEntityName() + "] for field [" + keyMap.getFieldName() + "]", module);
2743                return null;
2744            }
2745
2746            if (mainCols.length() > 0) {
2747                mainCols.append(", ");
2748            }
2749            mainCols.append(mainField.getColName());
2750        }
2751
2752        StringBuffer JavaDoc indexSqlBuf = new StringBuffer JavaDoc("CREATE INDEX ");
2753        String JavaDoc relConstraintName = makeFkConstraintName(modelRelation, constraintNameClipLength);
2754
2755        indexSqlBuf.append(relConstraintName);
2756        indexSqlBuf.append(" ON ");
2757        indexSqlBuf.append(entity.getTableName(datasourceInfo));
2758
2759        indexSqlBuf.append(" (");
2760        indexSqlBuf.append(mainCols.toString());
2761        indexSqlBuf.append(")");
2762
2763        return indexSqlBuf.toString();
2764    }
2765
2766    public void deleteForeignKeyIndices(ModelEntity entity, List JavaDoc messages) {
2767        if (messages == null) messages = new ArrayList JavaDoc();
2768        String JavaDoc err = deleteForeignKeyIndices(entity, datasourceInfo.constraintNameClipLength);
2769        if (!UtilValidate.isEmpty(err)) {
2770            messages.add(err);
2771        }
2772    }
2773
2774    public String JavaDoc deleteForeignKeyIndices(ModelEntity entity, int constraintNameClipLength) {
2775        if (entity == null) {
2776            return "ModelEntity was null and is required to delete foreign keys indices for a table";
2777        }
2778        if (entity instanceof ModelViewEntity) {
2779            return "ERROR: Cannot delete foreign keys indices for a view entity";
2780        }
2781
2782        StringBuffer JavaDoc retMsgsBuffer = new StringBuffer JavaDoc();
2783
2784        // go through the relationships to see if any foreign keys need to be added
2785
Iterator JavaDoc relationsIter = entity.getRelationsIterator();
2786
2787        while (relationsIter.hasNext()) {
2788            ModelRelation modelRelation = (ModelRelation) relationsIter.next();
2789
2790            if ("one".equals(modelRelation.getType())) {
2791                String JavaDoc retMsg = deleteForeignKeyIndex(entity, modelRelation, constraintNameClipLength);
2792
2793                if (retMsg != null && retMsg.length() > 0) {
2794                    if (retMsgsBuffer.length() > 0) {
2795                        retMsgsBuffer.append("\n");
2796                    }
2797                    retMsgsBuffer.append(retMsg);
2798                }
2799            }
2800        }
2801        if (retMsgsBuffer.length() > 0) {
2802            return retMsgsBuffer.toString();
2803        } else {
2804            return null;
2805        }
2806    }
2807
2808    public String JavaDoc deleteForeignKeyIndex(ModelEntity entity, ModelRelation modelRelation, int constraintNameClipLength) {
2809        Connection JavaDoc connection = null;
2810        Statement JavaDoc stmt = null;
2811
2812        try {
2813            connection = getConnection();
2814        } catch (SQLException JavaDoc sqle) {
2815            return "Unable to esablish a connection with the database... Error was: " + sqle.toString();
2816        } catch (GenericEntityException e) {
2817            return "Unable to esablish a connection with the database... Error was: " + e.toString();
2818        }
2819
2820        StringBuffer JavaDoc indexSqlBuf = new StringBuffer JavaDoc("DROP INDEX ");
2821        String JavaDoc relConstraintName = makeFkConstraintName(modelRelation, constraintNameClipLength);
2822
2823        String JavaDoc tableName = entity.getTableName(datasourceInfo);
2824        String JavaDoc schemaName = (tableName == null || tableName.length() == 0 || tableName.indexOf('.') == -1) ? "" :
2825                tableName.substring(0, tableName.indexOf('.'));
2826
2827        if (UtilValidate.isNotEmpty(schemaName)) {
2828            indexSqlBuf.append(schemaName);
2829            indexSqlBuf.append(".");
2830        }
2831        indexSqlBuf.append(relConstraintName);
2832
2833        String JavaDoc deleteIndexSql = indexSqlBuf.toString();
2834
2835        if (Debug.verboseOn()) Debug.logVerbose("[deleteForeignKeyIndex] index sql=" + deleteIndexSql, module);
2836
2837        try {
2838            stmt = connection.createStatement();
2839            stmt.executeUpdate(deleteIndexSql);
2840        } catch (SQLException JavaDoc sqle) {
2841            return "SQL Exception while executing the following:\n" + deleteIndexSql + "\nError was: " + sqle.toString();
2842        } finally {
2843            try {
2844                if (stmt != null) {
2845                    stmt.close();
2846                }
2847            } catch (SQLException JavaDoc sqle) {
2848                Debug.logError(sqle, module);
2849            }
2850            try {
2851                if (connection != null) {
2852                    connection.close();
2853                }
2854            } catch (SQLException JavaDoc sqle) {
2855                Debug.logError(sqle, module);
2856            }
2857        }
2858        return null;
2859    }
2860
2861    public String JavaDoc getSchemaName(DatabaseMetaData JavaDoc dbData) throws SQLException JavaDoc {
2862        if (!isLegacy && this.datasourceInfo.useSchemas && dbData.supportsSchemasInTableDefinitions()) {
2863            if (this.datasourceInfo.schemaName != null && this.datasourceInfo.schemaName.length() > 0) {
2864                return this.datasourceInfo.schemaName;
2865            } else {
2866                return dbData.getUserName();
2867            }
2868        }
2869        return null;
2870    }
2871
2872    /* ====================================================================== */
2873    /* ====================================================================== */
2874    public void updateCharacterSetAndCollation(ModelEntity entity, List JavaDoc messages) {
2875        if (entity instanceof ModelViewEntity) {
2876            return;
2877        }
2878        if (UtilValidate.isEmpty(this.datasourceInfo.characterSet) && UtilValidate.isEmpty(this.datasourceInfo.collate)) {
2879            messages.add("Not setting character-set and collate for entity [" + entity.getEntityName() + "], options not specified in the datasource definition in the entityengine.xml file.");
2880            return;
2881        }
2882
2883        Connection JavaDoc connection = null;
2884
2885        try {
2886            Statement JavaDoc stmt = null;
2887
2888            try {
2889                connection = getConnection();
2890            } catch (SQLException JavaDoc sqle) {
2891                messages.add("Unable to esablish a connection with the database... Error was: " + sqle.toString());
2892            } catch (GenericEntityException e) {
2893                messages.add("Unable to esablish a connection with the database... Error was: " + e.toString());
2894            }
2895            if (connection == null) {
2896                return;
2897            }
2898
2899            StringBuffer JavaDoc sqlTableBuf = new StringBuffer JavaDoc("ALTER TABLE ");
2900            sqlTableBuf.append(entity.getTableName(this.datasourceInfo));
2901            //sqlTableBuf.append("");
2902

2903            // if there is a characterSet, add the CHARACTER SET arg here
2904
if (UtilValidate.isNotEmpty(this.datasourceInfo.characterSet)) {
2905                sqlTableBuf.append(" DEFAULT CHARACTER SET ");
2906                sqlTableBuf.append(this.datasourceInfo.characterSet);
2907            }
2908            // if there is a collate, add the COLLATE arg here
2909
if (UtilValidate.isNotEmpty(this.datasourceInfo.collate)) {
2910                sqlTableBuf.append(" COLLATE ");
2911                sqlTableBuf.append(this.datasourceInfo.collate);
2912            }
2913
2914            if (Debug.verboseOn()) Debug.logVerbose("[updateCharacterSetAndCollation] character-set and collate sql=" + sqlTableBuf, module);
2915
2916            try {
2917                stmt = connection.createStatement();
2918                stmt.executeUpdate(sqlTableBuf.toString());
2919            } catch (SQLException JavaDoc sqle) {
2920                String JavaDoc errMsg = "SQL Exception while executing the following:\n" + sqlTableBuf + "\nError was: " + sqle.toString();
2921                messages.add(errMsg);
2922                Debug.logError(errMsg, module);
2923            } finally {
2924                try {
2925                    if (stmt != null)
2926                        stmt.close();
2927                } catch (SQLException JavaDoc sqle) {
2928                    Debug.logError(sqle, module);
2929                }
2930            }
2931
2932            Iterator JavaDoc fieldIter = entity.getFieldsIterator();
2933            while (fieldIter.hasNext()) {
2934                ModelField field = (ModelField) fieldIter.next();
2935                ModelFieldType type = modelFieldTypeReader.getModelFieldType(field.getType());
2936                if (type == null) {
2937                    messages.add("Field type [" + type + "] not found for field [" + field.getName() + "] of entity [" + entity.getEntityName() + "], not creating table.");
2938                    continue;
2939                }
2940                if(!"String".equals(type.getJavaType()) && !"java.lang.String".equals(type.getJavaType())) {
2941                    continue;
2942                }
2943
2944                StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc("ALTER TABLE ");
2945                sqlBuf.append(entity.getTableName(this.datasourceInfo));
2946                sqlBuf.append(" MODIFY COLUMN ");
2947                sqlBuf.append(field.getColName());
2948                sqlBuf.append(" ");
2949                sqlBuf.append(type.getSqlType());
2950
2951                // if there is a characterSet, add the CHARACTER SET arg here
2952
if (UtilValidate.isNotEmpty(this.datasourceInfo.characterSet)) {
2953                    sqlBuf.append(" CHARACTER SET ");
2954                    sqlBuf.append(this.datasourceInfo.characterSet);
2955                }
2956                // if there is a collate, add the COLLATE arg here
2957
if (UtilValidate.isNotEmpty(this.datasourceInfo.collate)) {
2958                    sqlBuf.append(" COLLATE ");
2959                    sqlBuf.append(this.datasourceInfo.collate);
2960                }
2961
2962                if (field.getIsPk()) {
2963                    if (this.datasourceInfo.alwaysUseConstraintKeyword) {
2964                        sqlBuf.append(" CONSTRAINT NOT NULL");
2965                    } else {
2966                        sqlBuf.append(" NOT NULL");
2967                    }
2968                }
2969
2970                if (Debug.verboseOn()) Debug.logVerbose("[updateCharacterSetAndCollation] character-set and collate sql=" + sqlBuf, module);
2971                try {
2972                    stmt = connection.createStatement();
2973                    stmt.executeUpdate(sqlBuf.toString());
2974                } catch (SQLException JavaDoc sqle) {
2975                    String JavaDoc errMsg = "SQL Exception while executing the following:\n" + sqlBuf + "\nError was: " + sqle.toString();
2976                    messages.add(errMsg);
2977                    Debug.logError(errMsg, module);
2978                } finally {
2979                    try {
2980                        if (stmt != null)
2981                            stmt.close();
2982                    } catch (SQLException JavaDoc sqle) {
2983                        Debug.logError(sqle, module);
2984                    }
2985                }
2986            }
2987        } finally {
2988            try {
2989                if (connection != null) {
2990                    connection.close();
2991                }
2992            } catch (SQLException JavaDoc sqle) {
2993                Debug.logError(sqle, module);
2994            }
2995        }
2996    }
2997
2998    /* ====================================================================== */
2999    /* ====================================================================== */
3000    public static class ColumnCheckInfo implements Serializable JavaDoc {
3001        public String JavaDoc tableName;
3002        public String JavaDoc columnName;
3003        public String JavaDoc typeName;
3004        public int columnSize;
3005        public int decimalDigits;
3006        public String JavaDoc isNullable; // YES/NO or "" = ie nobody knows
3007
public boolean isPk = false;
3008        public int pkSeq;
3009        public String JavaDoc pkName;
3010
3011        public static String JavaDoc fixupTableName(String JavaDoc rawTableName, String JavaDoc lookupSchemaName, boolean needsUpperCase) {
3012            String JavaDoc tableName = rawTableName;
3013            // for those databases which do not return the schema name with the table name (pgsql 7.3)
3014
boolean appendSchemaName = false;
3015            if (tableName != null && lookupSchemaName != null && !tableName.startsWith(lookupSchemaName)) {
3016                appendSchemaName = true;
3017            }
3018            if (needsUpperCase && tableName != null) {
3019                tableName = tableName.toUpperCase();
3020            }
3021            if (appendSchemaName) {
3022                tableName = lookupSchemaName + "." + tableName;
3023            }
3024            return tableName;
3025        }
3026    }
3027
3028    public static class ReferenceCheckInfo implements Serializable JavaDoc {
3029        public String JavaDoc pkTableName;
3030
3031        /** Comma separated list of column names in the related tables primary key */
3032        public String JavaDoc pkColumnName;
3033        public String JavaDoc fkName;
3034        public String JavaDoc fkTableName;
3035
3036        /** Comma separated list of column names in the primary tables foreign keys */
3037        public String JavaDoc fkColumnName;
3038
3039        public String JavaDoc toString() {
3040            return "FK Reference from table " + fkTableName + " called " + fkName + " to PK in table " + pkTableName;
3041        }
3042    }
3043}
3044
Popular Tags