diff --git a/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java b/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java index cc85153..eda0029 100644 --- a/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java +++ b/src/java/com/samskivert/jdbc/depot/DepotMarshaller.java @@ -714,12 +714,8 @@ public class DepotMarshaller ctx.invoke(new Modifier.Simple(indexdef)); } - // remove any extra columns - for (String column : columns) { - log.info("Dropping old column '" + column + "' from " + getTableName()); - String query = "alter table " + getTableName() + " drop index " + column; - ctx.invoke(new Modifier.Simple(query)); - } + // we do not hand remove columns but rather require that EntityMigration.Drop records be + // registered by hand to avoid accidentally causin the loss of data // remove any extra indices for (String index : indices) { diff --git a/src/java/com/samskivert/jdbc/depot/EntityMigration.java b/src/java/com/samskivert/jdbc/depot/EntityMigration.java index 588d266..d5ec6cc 100644 --- a/src/java/com/samskivert/jdbc/depot/EntityMigration.java +++ b/src/java/com/samskivert/jdbc/depot/EntityMigration.java @@ -20,6 +20,13 @@ package com.samskivert.jdbc.depot; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; + +import static com.samskivert.jdbc.depot.Log.log; + /** * These can be registered with the {@link PersistenceContext} to effect hand-coded migrations * between entity versions. The modifier should override {@link #invoke} to perform its @@ -28,6 +35,63 @@ package com.samskivert.jdbc.depot; */ public abstract class EntityMigration extends Modifier { + /** + * A convenient migration for dropping a column from an entity. + */ + public static class Drop extends EntityMigration + { + public Drop (int targetVersion, String columnName) { + super(targetVersion); + _columnName = columnName; + } + + public int invoke (Connection conn) throws SQLException { + Statement stmt = conn.createStatement(); + try { + log.info("Dropping '" + _columnName + "' from " + _tableName); + return stmt.executeUpdate( + "alter table " + _tableName + " drop column " + _columnName); + } finally { + stmt.close(); + } + } + + protected String _columnName; + } + + /** + * A convenient migration for renaming a column in an entity. + */ + public static class Rename extends EntityMigration + { + public Rename (int targetVersion, String oldColumnName, String newColumnName) { + super(targetVersion); + _oldColumnName = oldColumnName; + _newColumnName = newColumnName; + } + + public int invoke (Connection conn) throws SQLException { + Statement stmt = conn.createStatement(); + try { + log.info("Changing '" + _oldColumnName + "' to '" + _newColumnDef + "' in " + + _tableName); + return stmt.executeUpdate( + "alter table " + _tableName + " change column " + _oldColumnName + " " + + _newColumnDef); + } finally { + stmt.close(); + } + } + + protected void init (String tableName, HashMap marshallers) + { + super.init(tableName, marshallers); + _newColumnDef = marshallers.get(_newColumnName).getColumnDefinition(); + } + + protected String _oldColumnName, _newColumnName, _newColumnDef; + } + /** * If this method returns true, this migration will be run before the default * migrations, if false it will be run after. @@ -39,12 +103,29 @@ public abstract class EntityMigration extends Modifier /** * When an Entity is being migrated, this method will be called to check whether this migration - * should be run. + * should be run. The default implementation runs as long as the currentVersion is less than + * the target version supplied to the migration at construct time. */ - public abstract boolean shouldRunMigration (int currentVersion, int targetVersion); + public boolean shouldRunMigration (int currentVersion, int targetVersion) + { + return (currentVersion < _targetVersion); + } - protected EntityMigration () + protected EntityMigration (int targetVersion) { super(null); + _targetVersion = targetVersion; } + + /** + * This is called to provide the migration with the name of the entity table and access to its + * field marshallers prior to being invoked. + */ + protected void init (String tableName, HashMap marshallers) + { + _tableName = tableName; + } + + protected int _targetVersion; + protected String _tableName; }