Created an explicit EntityMigration.Add for when you want to add a column to a
database and need to provide a defaultValue at the time that you add it, but don't want to have to define a permanent default value on the field. git-svn-id: https://samskivert.googlecode.com/svn/trunk@2409 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -160,6 +160,21 @@ public abstract class BaseLiaison implements DatabaseLiaison
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
public boolean addColumn (Connection conn, String table, String column,
|
||||
ColumnDefinition newColumnDef, boolean check)
|
||||
throws SQLException
|
||||
{
|
||||
if (check && tableContainsColumn(conn, table, column)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
executeQuery(conn, "ALTER TABLE " + tableSQL(table) + " ADD COLUMN " +
|
||||
columnSQL(column) + " " + expandDefinition(newColumnDef));
|
||||
log.info("Database column '" + column + "' added to table '" + table + "'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// from DatabaseLiaison
|
||||
public boolean changeColumn (Connection conn, String table, String column, String type,
|
||||
Boolean nullable, Boolean unique, String defaultValue)
|
||||
|
||||
@@ -114,11 +114,19 @@ public interface DatabaseLiaison
|
||||
Connection conn, String table, String column, String definition, boolean check)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Adds a column to a table with the given definition. Tests for the previous existence of
|
||||
* the column iff 'check' is true.
|
||||
*/
|
||||
public boolean addColumn (
|
||||
Connection conn, String table, String column, ColumnDefinition columnDef, boolean check)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* Alter the definition, but not the name, of a given column on a given table. Returns true or
|
||||
* false if the database did or did not report a schema modification. Any of the type,
|
||||
* nullable, unique and defaultValue arguments may be null, in which case the implementation
|
||||
* will attempt to leave that aspect of the column unchanged.
|
||||
* false if the database did or did not report a schema modification. Any of the nullable,
|
||||
* unique and defaultValue arguments may be null, in which case the implementation will attempt
|
||||
* to leave that aspect of the column unchanged.
|
||||
*/
|
||||
public boolean changeColumn (
|
||||
Connection conn, String table, String column, String type, Boolean nullable,
|
||||
|
||||
@@ -150,6 +150,52 @@ public abstract class EntityMigration extends Modifier
|
||||
protected ColumnDefinition _newColumnDef;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenient migration for adding a new column that requires a default value to be specified
|
||||
* during the addition. Normally Depot will automatically handle column addition, but if you
|
||||
* have a column that normally does not have a default value but needs one when it is added to
|
||||
* a table with existing rows, you can use this migration.
|
||||
*
|
||||
* @see Column#defaultValue
|
||||
*/
|
||||
public static class Add extends EntityMigration
|
||||
{
|
||||
public Add (int targetVersion, String fieldName, String defaultValue) {
|
||||
super(targetVersion);
|
||||
_fieldName = fieldName;
|
||||
_defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@Override public int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException {
|
||||
// override the default value in the column definition with the one provided
|
||||
ColumnDefinition defColumnDef = new ColumnDefinition(
|
||||
_newColumnDef.getType(), _newColumnDef.isNullable(),
|
||||
_newColumnDef.isUnique(), _defaultValue);
|
||||
// first add the column with the overridden default value
|
||||
if (liaison.addColumn(conn, _tableName, _fieldName, defColumnDef, true)) {
|
||||
// then change the column to the permanent default value
|
||||
liaison.changeColumn(conn, _tableName, _fieldName, _newColumnDef.getType(),
|
||||
null, null, _newColumnDef.getDefaultValue());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public boolean runBeforeDefault () {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init (String tableName, Map<String, FieldMarshaller<?>> marshallers) {
|
||||
super.init(tableName, marshallers);
|
||||
_columnName = marshallers.get(_fieldName).getColumnName();
|
||||
_newColumnDef = marshallers.get(_fieldName).getColumnDefinition();
|
||||
}
|
||||
|
||||
protected String _fieldName, _columnName, _defaultValue;
|
||||
protected ColumnDefinition _newColumnDef;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this method returns true, this migration will be run <b>before</b> the default
|
||||
* migrations, if false it will be run after.
|
||||
|
||||
@@ -61,6 +61,13 @@ public class TestRecord extends PersistentRecord
|
||||
public static final ColumnExp AGE_C =
|
||||
new ColumnExp(TestRecord.class, AGE);
|
||||
|
||||
/** The column identifier for the {@link #homeTown} field. */
|
||||
public static final String HOME_TOWN = "homeTown";
|
||||
|
||||
/** The qualified column identifier for the {@link #homeTown} field. */
|
||||
public static final ColumnExp HOME_TOWN_C =
|
||||
new ColumnExp(TestRecord.class, HOME_TOWN);
|
||||
|
||||
/** The column identifier for the {@link #created} field. */
|
||||
public static final String CREATED = "created";
|
||||
|
||||
@@ -76,21 +83,19 @@ public class TestRecord extends PersistentRecord
|
||||
new ColumnExp(TestRecord.class, LAST_MODIFIED);
|
||||
// AUTO-GENERATED: FIELDS END
|
||||
|
||||
public static final int SCHEMA_VERSION = 1;
|
||||
public static final int SCHEMA_VERSION = 2;
|
||||
|
||||
@Id
|
||||
public int recordId;
|
||||
|
||||
@Column(nullable=false)
|
||||
public String name;
|
||||
|
||||
@Column(nullable=false)
|
||||
public int age;
|
||||
|
||||
@Column(nullable=false)
|
||||
public String homeTown;
|
||||
|
||||
public Date created;
|
||||
|
||||
@Column(nullable=false)
|
||||
public Timestamp lastModified;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,11 +24,10 @@ import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Set;
|
||||
|
||||
// import com.samskivert.jdbc.ConnectionProvider;
|
||||
import com.samskivert.jdbc.StaticConnectionProvider;
|
||||
import com.samskivert.util.RandomUtil;
|
||||
import com.samskivert.jdbc.depot.DepotRepository;
|
||||
// import com.samskivert.jdbc.depot.EntityMigration;
|
||||
import com.samskivert.jdbc.depot.EntityMigration;
|
||||
import com.samskivert.jdbc.depot.PersistenceContext;
|
||||
import com.samskivert.jdbc.depot.PersistentRecord;
|
||||
import com.samskivert.jdbc.depot.expression.LiteralExp;
|
||||
@@ -46,8 +45,12 @@ public class TestRepository extends DepotRepository
|
||||
PersistenceContext perCtx = new PersistenceContext(
|
||||
"test", new StaticConnectionProvider("depot.properties"));
|
||||
|
||||
// tests a bogus rename migration
|
||||
// perCtx.registerMigration(TestRecord.class, new EntityMigration.Rename(1, "foo", "bar"));
|
||||
// tests a bogus rename migration
|
||||
// perCtx.registerMigration(TestRecord.class, new EntityMigration.Rename(1, "foo", "bar"));
|
||||
|
||||
// tests a custom add column migration
|
||||
perCtx.registerMigration(TestRecord.class,
|
||||
new EntityMigration.Add(2, TestRecord.HOME_TOWN, "'Anytown USA'"));
|
||||
|
||||
TestRepository repo = new TestRepository(perCtx);
|
||||
|
||||
@@ -60,6 +63,7 @@ public class TestRepository extends DepotRepository
|
||||
record.name = "Elvis";
|
||||
record.age = 99;
|
||||
record.created = now;
|
||||
record.homeTown = "Right here";
|
||||
record.lastModified = tnow;
|
||||
|
||||
repo.insert(record);
|
||||
@@ -75,6 +79,7 @@ public class TestRepository extends DepotRepository
|
||||
record.recordId = ii;
|
||||
record.name = "Spam!";
|
||||
record.age = RandomUtil.getInt(150);
|
||||
record.homeTown = "Over there";
|
||||
record.created = now;
|
||||
record.lastModified = tnow;
|
||||
repo.insert(record);
|
||||
|
||||
Reference in New Issue
Block a user