diff --git a/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java b/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java index b6de2d1..1a87be2 100644 --- a/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java +++ b/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java @@ -531,18 +531,20 @@ public class DepotMarshaller }); // fetch all relevant information regarding our table from the database - final TableMetaData metaData = ctx.invoke(new Query.TrivialQuery() { - public TableMetaData invoke (Connection conn, DatabaseLiaison dl) throws SQLException { - return new TableMetaData(conn.getMetaData()); - } - }); + TableMetaData metaData = TableMetaData.load(ctx, getTableName()); // compute relevant information from our persistent record, too - final RecordMetaData rMeta = new RecordMetaData(_pclass, _fields); + RecordMetaData rMeta = new RecordMetaData(_pclass, _fields); // if the table does not exist, create it if (!metaData.tableExists) { final String[] fDeclarations = declarations; + final String[][] uniqueConCols = new String[rMeta.uniqueConstraints.size()][]; + int kk = 0; + for (Set colSet : rMeta.uniqueConstraints) { + uniqueConCols[kk++] = colSet.toArray(new String[colSet.size()]); + } + final Iterable indexen = rMeta.indices.values(); ctx.invoke(new Modifier() { public int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException { // create the table @@ -557,16 +559,11 @@ public class DepotMarshaller primaryKeyColumns[ii] = _pkColumns.get(ii).getColumnName(); } } - String[][] uniqueConCols = new String[rMeta.uniqueConstraints.size()][]; - int kk = 0; - for (Set colSet : rMeta.uniqueConstraints) { - uniqueConCols[kk++] = colSet.toArray(new String[colSet.size()]); - } liaison.createTableIfMissing(conn, getTableName(), columns, fDeclarations, uniqueConCols, primaryKeyColumns); // add its indexen - for (Index idx : rMeta.indices.values()) { + for (Index idx : indexen) { liaison.addIndexToTable( conn, getTableName(), idx.columns(), getTableName() + "_" + idx.name(), idx.unique()); @@ -621,13 +618,18 @@ public class DepotMarshaller log.info("Migrating " + getTableName() + " from " + currentVersion + " to " + _schemaVersion + "..."); - // run our pre-default-migrations - for (EntityMigration migration : _migrations) { - if (migration.runBeforeDefault() && - migration.shouldRunMigration(currentVersion, _schemaVersion)) { - migration.init(getTableName(), _fields); - ctx.invoke(migration); + if (_migrations.size() > 0) { + // run our pre-default-migrations + for (EntityMigration migration : _migrations) { + if (migration.runBeforeDefault() && + migration.shouldRunMigration(currentVersion, _schemaVersion)) { + migration.init(getTableName(), _fields); + ctx.invoke(migration); + } } + + // we don't know what the pre-migrations did so we have to re-read metadata + metaData = TableMetaData.load(ctx, getTableName()); } // this is a little silly, but we need a copy for name disambiguation later @@ -635,7 +637,7 @@ public class DepotMarshaller // add any missing columns for (String fname : _columnFields) { - @SuppressWarnings("unchecked") final FieldMarshaller fmarsh = _fields.get(fname); + final FieldMarshaller fmarsh = _fields.get(fname); if (metaData.tableColumns.remove(fmarsh.getColumnName())) { continue; } @@ -680,10 +682,11 @@ public class DepotMarshaller }); } else if (!hasPrimaryKey() && metaData.pkName != null) { - log.info("Dropping primary key."); + final String pkName = metaData.pkName; + log.info("Dropping primary key: " + pkName); ctx.invoke(new Modifier() { public int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException { - liaison.dropPrimaryKey(conn, getTableName(), metaData.pkName); + liaison.dropPrimaryKey(conn, getTableName(), pkName); return 0; } }); @@ -761,7 +764,7 @@ public class DepotMarshaller }); } - protected class TableMetaData + protected static class TableMetaData { public boolean tableExists; public Set tableColumns = new HashSet(); @@ -769,20 +772,31 @@ public class DepotMarshaller public String pkName; public Set pkColumns = new HashSet(); - public TableMetaData (DatabaseMetaData meta) + public static TableMetaData load (PersistenceContext ctx, final String tableName) + throws PersistenceException + { + return ctx.invoke(new Query.TrivialQuery() { + public TableMetaData invoke (Connection conn, DatabaseLiaison dl) + throws SQLException { + return new TableMetaData(conn.getMetaData(), tableName); + } + }); + } + + public TableMetaData (DatabaseMetaData meta, String tableName) throws SQLException { - tableExists = meta.getTables("", "", getTableName(), null).next(); + tableExists = meta.getTables("", "", tableName, null).next(); if (!tableExists) { return; } - ResultSet rs = meta.getColumns(null, null, getTableName(), "%"); + ResultSet rs = meta.getColumns(null, null, tableName, "%"); while (rs.next()) { tableColumns.add(rs.getString("COLUMN_NAME")); } - rs = meta.getIndexInfo(null, null, getTableName(), false, false); + rs = meta.getIndexInfo(null, null, tableName, false, false); while (rs.next()) { String indexName = rs.getString("INDEX_NAME"); Set set = indexColumns.get(indexName); @@ -802,7 +816,7 @@ public class DepotMarshaller } } - rs = meta.getPrimaryKeys(null, null, getTableName()); + rs = meta.getPrimaryKeys(null, null, tableName); while (rs.next()) { pkName = rs.getString("PK_NAME"); pkColumns.add(rs.getString("COLUMN_NAME")); diff --git a/src/java/com/samskivert/jdbc/depot/EntityMigration.java b/src/java/com/samskivert/jdbc/depot/EntityMigration.java index 01397a8..9bea2bd 100644 --- a/src/java/com/samskivert/jdbc/depot/EntityMigration.java +++ b/src/java/com/samskivert/jdbc/depot/EntityMigration.java @@ -3,7 +3,7 @@ // // samskivert library - useful routines for java programs // Copyright (C) 2006-2007 Michael Bayne, Pär Winzell -// +// // This library is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation; either version 2.1 of the License, or @@ -25,8 +25,6 @@ import java.sql.SQLException; import java.util.Map; import com.samskivert.jdbc.DatabaseLiaison; -import com.samskivert.jdbc.JDBCUtil; -import com.samskivert.jdbc.LiaisonRegistry; import static com.samskivert.jdbc.depot.Log.log; @@ -49,7 +47,7 @@ public abstract class EntityMigration extends Modifier } public int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException { - if (!JDBCUtil.tableContainsColumn(conn, _tableName, _columnName)) { + if (!liaison.tableContainsColumn(conn, _tableName, _columnName)) { // we'll accept this inconsistency log.warning(_tableName + "." + _columnName + " already dropped."); return 0; @@ -74,8 +72,8 @@ public abstract class EntityMigration extends Modifier } public int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException { - if (!JDBCUtil.tableContainsColumn(conn, _tableName, _oldColumnName)) { - if (JDBCUtil.tableContainsColumn(conn, _tableName, _newColumnName)) { + if (!liaison.tableContainsColumn(conn, _tableName, _oldColumnName)) { + if (liaison.tableContainsColumn(conn, _tableName, _newColumnName)) { // we'll accept this inconsistency log.warning(_tableName + "." + _oldColumnName + " already renamed to " + _newColumnName + "."); @@ -87,7 +85,7 @@ public abstract class EntityMigration extends Modifier } // nor is this - if (JDBCUtil.tableContainsColumn(conn, _tableName, _newColumnName)) { + if (liaison.tableContainsColumn(conn, _tableName, _newColumnName)) { throw new IllegalArgumentException( _tableName + " already contains '" + _newColumnName + "'"); } @@ -98,7 +96,7 @@ public abstract class EntityMigration extends Modifier } public boolean runBeforeDefault () { - return false; + return true; } protected String _oldColumnName, _newColumnName; diff --git a/src/java/com/samskivert/jdbc/depot/SQLBuilder.java b/src/java/com/samskivert/jdbc/depot/SQLBuilder.java index 9295155..37d192c 100644 --- a/src/java/com/samskivert/jdbc/depot/SQLBuilder.java +++ b/src/java/com/samskivert/jdbc/depot/SQLBuilder.java @@ -96,7 +96,7 @@ public abstract class SQLBuilder * TODO: This method should be split into several parts that are more easily overridden on a * case-by-case basis in the dialectal subclasses. */ - public String buildColumnDefinition (FieldMarshaller fm) + public String buildColumnDefinition (FieldMarshaller fm) { // if this field is @Computed, it has no SQL definition if (fm.getComputed() != null) {