Author: [EMAIL PROTECTED]
Date: Thu Aug 28 11:09:59 2008
New Revision: 2648
Modified:
trunk/src/ca/sqlpower/architect/SQLColumn.java
trunk/src/ca/sqlpower/architect/SQLIndex.java
trunk/src/ca/sqlpower/architect/SQLRelationship.java
trunk/src/ca/sqlpower/architect/SQLTable.java
Log:
In order DatabaseMetaData caching to work properly, the methods used for
populating SQLColumn, SQLIndex, SQLRelationship, and SQLTable need to pass
a common DatabaseMetaData object so that they all use the same cache stored
within it (caching is as of this commit only used in the
OracleDatabaseMetaDataDecorator). Otherwise, each method call would end up
creating a new DatabaseMetaData object each time, resulting in the cache
being refreshed each time, which ends up worsening performance.
Modified: trunk/src/ca/sqlpower/architect/SQLColumn.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/SQLColumn.java (original)
+++ trunk/src/ca/sqlpower/architect/SQLColumn.java Thu Aug 28 11:09:59 2008
@@ -274,16 +274,16 @@
static void addColumnsToTable(SQLTable addTo,
String catalog,
String schema,
-
String tableName)
+
String tableName,
+
DatabaseMetaData dbmd)
throws SQLException, DuplicateColumnException,
ArchitectException {
Connection con = null;
ResultSet rs = null;
ResultSet typeRs = null;
- DatabaseMetaData dbmd = null;
try {
con = addTo.getParentDatabase().getConnection();
- dbmd = con.getMetaData();
+ if (dbmd == null) dbmd = con.getMetaData();
typeRs = con.getMetaData().getTypeInfo();
Map<Double, Double> typeToMaxPrecisionMap = new HashMap<Double,
Double>();
while (typeRs.next()) {
Modified: trunk/src/ca/sqlpower/architect/SQLIndex.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/SQLIndex.java (original)
+++ trunk/src/ca/sqlpower/architect/SQLIndex.java Thu Aug 28 11:09:59 2008
@@ -585,19 +585,18 @@
* SQLObjectEvents to avoid infinite recursion, so you have to
* generate them yourself at a safe time.
*/
- static void addIndicesToTable(SQLTable addTo, String catalog, String
schema, String tableName) throws SQLException,
+ static void addIndicesToTable(SQLTable addTo, String catalog, String
schema, String tableName, DatabaseMetaData dbmd) throws SQLException,
ArchitectException {
Connection con = null;
ResultSet rs = null;
- DatabaseMetaData dbmd = null;
try {
con = addTo.getParentDatabase().getConnection();
- dbmd = con.getMetaData();
+ if (dbmd == null) dbmd = con.getMetaData();
String pkName = null;
rs = dbmd.getPrimaryKeys(catalog, schema, tableName);
while (rs.next()) {
- SQLColumn col = addTo.getColumnByName(rs.getString(4),
false, true);
+ SQLColumn col = addTo.getColumnByName(rs.getString(4),
false, true, dbmd);
//logger.debug(rs.getString(4));
if (col != null) {
col.primaryKeySeq = new Integer(rs.getInt(5));
Modified: trunk/src/ca/sqlpower/architect/SQLRelationship.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/SQLRelationship.java (original)
+++ trunk/src/ca/sqlpower/architect/SQLRelationship.java Thu Aug 28
11:09:59 2008
@@ -340,6 +340,10 @@
* @throws ArchitectException
*/
public void attachRelationship(SQLTable pkTable, SQLTable fkTable,
boolean autoGenerateMapping) throws ArchitectException {
+ attachRelationship(pkTable, fkTable, autoGenerateMapping, null);
+ }
+
+ void attachRelationship(SQLTable pkTable, SQLTable fkTable, boolean
autoGenerateMapping, DatabaseMetaData dbmd) throws ArchitectException {
if(pkTable == null) throw new NullPointerException("Null pkTable not
allowed");
if(fkTable == null) throw new NullPointerException("Null fkTable not
allowed");
@@ -360,7 +364,7 @@
boolean alreadyExists = false;
- for (SQLRelationship r : pkTable.getExportedKeys()) {
+ for (SQLRelationship r : pkTable.getExportedKeys(dbmd))
{
if (r.getFkTable().equals(fkTable)) {
alreadyExists = true;
break;
@@ -502,18 +506,17 @@
* @throws ArchitectException if a database error occurs or if the
* given table's parent database is not marked as populated.
*/
- static void addImportedRelationshipsToTable(SQLTable table) throws
ArchitectException {
+ static void addImportedRelationshipsToTable(SQLTable table,
DatabaseMetaData dbmd) throws ArchitectException {
SQLDatabase db = table.getParentDatabase();
if (!db.isPopulated()) {
throw new
ArchitectException("relationship.unpopulatedTargetDatabase");
}
Connection con = null;
CachedRowSet crs = null;
- DatabaseMetaData dbmd = null;
ResultSet tempRS = null; // just a temporary place for the live result
set. use crs instead.
try {
con = db.getConnection();
- dbmd = con.getMetaData();
+ if (dbmd == null) dbmd = con.getMetaData();
crs = new CachedRowSet();
tempRS = dbmd.getImportedKeys(table.getCatalogName(),
table.getSchemaName(),
@@ -564,7 +567,7 @@
}
logger.debug("Looking for pk column '"+crs.getString(4)+"' in
table '"+r.pkTable+"'");
- m.pkColumn =
r.pkTable.getColumnByName(crs.getString(4));
+ m.pkColumn =
r.pkTable.getColumnByName(crs.getString(4), dbmd);
if (m.pkColumn == null) {
throw new
ArchitectException("relationship.populate.nullPkColumn");
}
@@ -595,7 +598,7 @@
// now that all the new SQLRelationship objects are set up, add them to
their tables
for (SQLRelationship addMe : newKeys) {
- addMe.attachRelationship(addMe.pkTable, addMe.fkTable,
false);
+ addMe.attachRelationship(addMe.pkTable, addMe.fkTable,
false, dbmd);
}
} catch (SQLException e) {
Modified: trunk/src/ca/sqlpower/architect/SQLTable.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/SQLTable.java (original)
+++ trunk/src/ca/sqlpower/architect/SQLTable.java Thu Aug 28 11:09:59 2008
@@ -185,17 +185,22 @@
*
* @throws ArchitectException
*/
- private synchronized void populateColumns() throws ArchitectException {
+ private synchronized void populateColumns() throws ArchitectException {
+ populateColumns(null);
+ }
+
+ private synchronized void populateColumns(DatabaseMetaData dbmd) throws
ArchitectException {
if (columnsFolder.isPopulated()) return;
if (columnsFolder.children.size() > 0) throw new
IllegalStateException("Can't populate table because it already contains
columns");
- logger.debug("column folder populate starting");
+ logger.debug("column folder populate starting for table " +
getName());
try {
SQLColumn.addColumnsToTable(this,
getCatalogName(),
getSchemaName(),
-
getName());
+
getName(),
+
dbmd);
} catch (SQLException e) {
throw new ArchitectException("Failed to populate columns of
table "+getName(), e);
} finally {
@@ -208,9 +213,9 @@
columnsFolder.fireDbChildrenInserted(changedIndices,
columnsFolder.children);
}
- logger.debug("column folder populate finished");
+ logger.debug("column folder populate finished for table " +
getName());
- populateIndices();
+ populateIndices(dbmd);
}
/**
@@ -224,7 +229,11 @@
* @throws IllegalStateException if the columns folder is not yet
populated, or if the
* index folder is both non-empty and non-populated
*/
- private synchronized void populateIndices() throws ArchitectException {
+ private synchronized void populateIndices() throws ArchitectException {
+ populateIndices(null);
+ }
+
+ private synchronized void populateIndices(DatabaseMetaData dbmd)
throws ArchitectException {
if (indicesFolder.isPopulated()) return;
if (indicesFolder.children.size() > 0) throw new
IllegalStateException("Can't populate indices folder because it already
contains children!");
if (!columnsFolder.isPopulated()) throw new
IllegalStateException("Columns folder must be populated");
@@ -244,7 +253,8 @@
SQLIndex.addIndicesToTable(this,
getCatalogName(),
getSchemaName(),
- getName());
+ getName(),
+ dbmd);
logger.debug("found "+indicesFolder.children.size()+"
indices.");
for (SQLColumn column : getColumns()) {
@@ -278,7 +288,11 @@
* side effect of populating the exported key side of the
* relationships for the exporting tables.
*/
- private synchronized void populateRelationships() throws
ArchitectException {
+ private synchronized void populateRelationships() throws
ArchitectException {
+ populateRelationships(null);
+ }
+
+ private synchronized void populateRelationships(DatabaseMetaData dbmd)
throws ArchitectException {
if (!columnsFolder.isPopulated()) throw new IllegalStateException("Table
must be populated before relationships are added");
if (importedKeysFolder.isPopulated()) return;
@@ -294,7 +308,7 @@
*/
importedKeysFolder.populated = true;
try {
- SQLRelationship.addImportedRelationshipsToTable(this);
+ SQLRelationship.addImportedRelationshipsToTable(this,
dbmd);
} finally {
int newSize = importedKeysFolder.children.size();
if (newSize > oldSize) {
@@ -440,8 +454,12 @@
* manner.
*/
public SQLColumn getColumnByName(String colName) throws
ArchitectException {
- return getColumnByName(colName, true, false);
+ return getColumnByName(colName, true, false, null);
}
+
+ public SQLColumn getColumnByName(String colName, DatabaseMetaData dbmd)
throws ArchitectException {
+ return getColumnByName(colName, true, false, dbmd);
+ }
/**
* Searches for the named column.
@@ -450,9 +468,14 @@
* list from the database; otherwise it just searches the current
* list.
*/
- public SQLColumn getColumnByName(String colName, boolean populate,
boolean caseSensitive)
+ public SQLColumn getColumnByName(String colName, boolean populate,
boolean caseSensitive)
+ throws ArchitectException {
+ return getColumnByName(colName, populate, caseSensitive, null);
+ }
+
+ public SQLColumn getColumnByName(String colName, boolean populate,
boolean caseSensitive, DatabaseMetaData dbmd)
throws ArchitectException {
- if (populate) populateColumns();
+ if (populate) populateColumns(dbmd);
/* if columnsFolder.children.iterator(); gets changed to
getColumns().iterator()
* we get infinite recursion between populateColumns,
getColumns,
* getColumnsByName and addColumnsToTable
@@ -461,8 +484,10 @@
logger.debug("Looking for column "+colName+"
in "+columnsFolder.children);
}
Iterator it = columnsFolder.children.iterator();
+ logger.debug("Table " + getName() + " has " +
columnsFolder.children.size() + " columns");
while (it.hasNext()) {
SQLColumn col = (SQLColumn) it.next();
+ logger.debug("Current column name is '" + col.getName() +
"'");
if (caseSensitive) {
if (col.getName().equals(colName)) {
logger.debug("FOUND");
@@ -891,23 +916,26 @@
}
public void populate() throws ArchitectException {
+ populate(null);
+ }
+
+ public void populate(DatabaseMetaData dbmd) throws
ArchitectException {
if (populated) return;
logger.debug("SQLTable.Folder["+getName()+"]: populate
starting");
try {
if (type == COLUMNS) {
- parent.populateColumns();
+ parent.populateColumns(dbmd);
} else if (type == IMPORTED_KEYS) {
- parent.populateColumns();
- parent.populateRelationships();
+ parent.populateColumns(dbmd);
+ parent.populateRelationships(dbmd);
} else if (type == EXPORTED_KEYS) {
CachedRowSet crs = null;
Connection con = null;
- DatabaseMetaData dbmd = null;
try {
con =
parent.getParentDatabase().getConnection();
- dbmd = con.getMetaData();
+ if (dbmd == null) dbmd =
con.getMetaData();
crs = new CachedRowSet();
ResultSet exportedKeysRS =
dbmd.getExportedKeys(parent.getCatalogName(), parent.getSchemaName(),
parent.getName());
crs.populate(exportedKeysRS);
@@ -939,8 +967,8 @@
", I failed to find child table " +
"\""+cat+"\".\""+sch+"\".\""+tab+"\"");
}
-
fkTable.populateColumns();
-
fkTable.populateRelationships();
+
fkTable.populateColumns(dbmd);
+
fkTable.populateRelationships(dbmd);
}
} catch (SQLException ex) {
throw new
ArchitectException("Couldn't locate related tables", ex);
@@ -1026,6 +1054,19 @@
return type;
}
+ /**
+ * Returns an unmodifiable view of the child list. All list
+ * members will be SQLObject subclasses (SQLTable,
+ * SQLRelationship, SQLColumn, etc.) which are directly contained
+ * within this SQLObject.
+ */
+ public List getChildren(DatabaseMetaData dbmd) throws
ArchitectException {
+ if (!allowsChildren()) //never return null;
+ return children;
+ populate(dbmd);
+ return Collections.unmodifiableList(children);
+ }
+
@Override
public Class<? extends SQLObject> getChildType() {
return SQLColumn.class;
@@ -1198,7 +1239,11 @@
* @return the value of exportedKeys
*/
public List<SQLRelationship> getExportedKeys() throws
ArchitectException {
- return this.exportedKeysFolder.getChildren();
+ return getExportedKeys(null);
+ }
+
+ public List<SQLRelationship> getExportedKeys(DatabaseMetaData dbmd)
throws ArchitectException {
+ return this.exportedKeysFolder.getChildren(dbmd);
}
/**