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);
        }

     /**

Reply via email to