mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 15:55:55 +00:00
#564 - DDL DB Migration - migration generation on history table, pending drop columns missing in the history view and tigger
This commit is contained in:
@@ -220,6 +220,9 @@ public class DbMigration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the diff migration.
|
||||
*/
|
||||
private void generateDiff(Request request) throws IOException {
|
||||
|
||||
List<String> pendingDrops = request.getPendingDrops();
|
||||
@@ -227,15 +230,18 @@ public class DbMigration {
|
||||
logger.info("Pending un-applied drops in versions {}", pendingDrops);
|
||||
}
|
||||
|
||||
ModelDiff diff = request.createDiff();
|
||||
if (diff.isEmpty()) {
|
||||
Migration migration = request.createDiffMigration();
|
||||
if (migration == null) {
|
||||
logger.info("no changes detected - no migration written");
|
||||
} else {
|
||||
// there were actually changes to write
|
||||
generateMigration(request, diff.getMigration(), null);
|
||||
generateMigration(request, migration, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the migration based on the pendingDrops from a prior version.
|
||||
*/
|
||||
private void generatePendingDrop(Request request, String pendingVersion) throws IOException {
|
||||
|
||||
Migration migration = request.migrationForPendingDrop(pendingVersion);
|
||||
@@ -290,12 +296,12 @@ public class DbMigration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an return the diff of the current model to the migration model.
|
||||
* Create and return the diff of the current model to the migration model.
|
||||
*/
|
||||
public ModelDiff createDiff() {
|
||||
public Migration createDiffMigration() {
|
||||
ModelDiff diff = new ModelDiff(migrated);
|
||||
diff.compareTo(current);
|
||||
return diff;
|
||||
return diff.isEmpty() ? null : diff.getMigration();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,12 +159,7 @@ public class CurrentModel {
|
||||
ModelDiff diff = new ModelDiff();
|
||||
diff.compareTo(model);
|
||||
|
||||
List<Object> applyChanges = diff.getApplyChanges();
|
||||
|
||||
// put the changes into a ChangeSet
|
||||
ChangeSet applyChangeSet = new ChangeSet();
|
||||
applyChangeSet.getChangeSetChildren().addAll(applyChanges);
|
||||
return applyChangeSet;
|
||||
return diff.getApplyChangeSet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -356,8 +356,9 @@ public class MTable {
|
||||
return withHistory;
|
||||
}
|
||||
|
||||
public void setWithHistory(boolean withHistory) {
|
||||
public MTable setWithHistory(boolean withHistory) {
|
||||
this.withHistory = withHistory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> allHistoryColumns(boolean includeDropped) {
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.avaje.ebean.dbmigration.migration.DropIndex;
|
||||
import com.avaje.ebean.dbmigration.migration.DropTable;
|
||||
import com.avaje.ebean.dbmigration.migration.Migration;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -45,8 +44,7 @@ public class ModelContainer {
|
||||
* Adjust the FK references on all the draft tables.
|
||||
*/
|
||||
public void adjustDraftReferences() {
|
||||
Collection<MTable> tables = this.tables.values();
|
||||
for (MTable table : tables) {
|
||||
for (MTable table : this.tables.values()) {
|
||||
if (table.isDraft()) {
|
||||
table.adjustReferences(this);
|
||||
}
|
||||
@@ -94,7 +92,7 @@ public class ModelContainer {
|
||||
pendingDrops.add(version, changeSet);
|
||||
|
||||
} else if (isDropsFor(changeSet)) {
|
||||
pendingDrops.appliedDropsFor(MigrationVersion.parse(changeSet.getDropsFor()));
|
||||
pendingDrops.appliedDropsFor(changeSet);
|
||||
}
|
||||
if (!isDropsFor(changeSet)) {
|
||||
applyChangeSet(changeSet);
|
||||
@@ -286,10 +284,26 @@ public class ModelContainer {
|
||||
pendingDrops.registerPendingHistoryDropColumns(newModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register any pending drop columns on history tables. These columns are now not in the current
|
||||
* logical model but we still need to include them in the history views and triggers until they
|
||||
* are actually dropped.
|
||||
*/
|
||||
public void registerPendingHistoryDropColumns(ChangeSet changeSet) {
|
||||
for (Object change : changeSet.getChangeSetChildren()) {
|
||||
if (change instanceof DropColumn) {
|
||||
DropColumn dropColumn = (DropColumn) change;
|
||||
if (Boolean.TRUE.equals(dropColumn.isWithHistory())) {
|
||||
registerPendingDropColumn(dropColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a drop column on a history tables that has not been applied yet.
|
||||
*/
|
||||
public void registerPendingDropColumn(DropColumn dropColumn) {
|
||||
private void registerPendingDropColumn(DropColumn dropColumn) {
|
||||
|
||||
MTable table = getTable(dropColumn.getTableName());
|
||||
if (table == null) {
|
||||
|
||||
@@ -66,16 +66,14 @@ public class ModelDiff {
|
||||
public Migration getMigration() {
|
||||
|
||||
Migration migration = new Migration();
|
||||
ChangeSet applyChangeSet = getApplyChangeSet();
|
||||
if (!applyChangeSet.getChangeSetChildren().isEmpty()) {
|
||||
if (!applyChanges.isEmpty()) {
|
||||
// add a non empty apply changeSet
|
||||
migration.getChangeSet().add(applyChangeSet);
|
||||
migration.getChangeSet().add(getApplyChangeSet());
|
||||
}
|
||||
|
||||
ChangeSet dropChangeSet = getDropChangeSet();
|
||||
if (!dropChangeSet.getChangeSetChildren().isEmpty()) {
|
||||
if (!dropChanges.isEmpty()) {
|
||||
// add a non empty drop changeSet
|
||||
migration.getChangeSet().add(dropChangeSet);
|
||||
migration.getChangeSet().add(getDropChangeSet());
|
||||
}
|
||||
return migration;
|
||||
}
|
||||
@@ -83,14 +81,14 @@ public class ModelDiff {
|
||||
/**
|
||||
* Return the list of 'apply' changes.
|
||||
*/
|
||||
public List<Object> getApplyChanges() {
|
||||
List<Object> getApplyChanges() {
|
||||
return applyChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of 'drop' changes.
|
||||
*/
|
||||
public List<Object> getDropChanges() {
|
||||
List<Object> getDropChanges() {
|
||||
return dropChanges;
|
||||
}
|
||||
|
||||
@@ -108,7 +106,7 @@ public class ModelDiff {
|
||||
/**
|
||||
* Return the 'drop' changeSet.
|
||||
*/
|
||||
public ChangeSet getDropChangeSet() {
|
||||
ChangeSet getDropChangeSet() {
|
||||
// put the changes into a ChangeSet
|
||||
ChangeSet createChangeSet = new ChangeSet();
|
||||
createChangeSet.setType(ChangeSetType.PENDING_DROPS);
|
||||
@@ -156,7 +154,12 @@ public class ModelDiff {
|
||||
}
|
||||
}
|
||||
|
||||
// register un-applied ones from the previous migrations
|
||||
baseModel.registerPendingHistoryDropColumns(newModel);
|
||||
if (!dropChanges.isEmpty()) {
|
||||
// register new ones created just now as part of this diff
|
||||
newModel.registerPendingHistoryDropColumns(getDropChangeSet());
|
||||
}
|
||||
}
|
||||
|
||||
protected void addDropTable(MTable existingTable) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.avaje.ebean.dbmigration.model;
|
||||
import com.avaje.ebean.dbmigration.migration.ChangeSet;
|
||||
import com.avaje.ebean.dbmigration.migration.ChangeSetType;
|
||||
import com.avaje.ebean.dbmigration.migration.DropColumn;
|
||||
import com.avaje.ebean.dbmigration.migration.DropTable;
|
||||
import com.avaje.ebean.dbmigration.migration.Migration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -48,9 +49,12 @@ public class PendingDrops {
|
||||
* All the pending drops for this migration version have been applied so we need
|
||||
* to remove the (unsuppressed) pending drops for this version.
|
||||
*/
|
||||
public boolean appliedDropsFor(MigrationVersion version) {
|
||||
public boolean appliedDropsFor(ChangeSet changeSet) {
|
||||
|
||||
MigrationVersion version = MigrationVersion.parse(changeSet.getDropsFor());
|
||||
|
||||
Entry entry = map.get(version.normalised());
|
||||
if (entry.removeDrops()) {
|
||||
if (entry.removeDrops(changeSet)) {
|
||||
// it had no suppressForever changeSets so remove completely
|
||||
map.remove(version.normalised());
|
||||
return true;
|
||||
@@ -70,8 +74,11 @@ public class PendingDrops {
|
||||
Entry entry = getEntry(pendingVersion);
|
||||
|
||||
Migration migration = new Migration();
|
||||
for (ChangeSet changeSet : entry.list) {
|
||||
Iterator<ChangeSet> it = entry.list.iterator();
|
||||
while (it.hasNext()) {
|
||||
ChangeSet changeSet = it.next();
|
||||
if (!isSuppressForever(changeSet)) {
|
||||
it.remove();
|
||||
changeSet.setType(ChangeSetType.APPLY);
|
||||
changeSet.setDropsFor(entry.version.asString());
|
||||
migration.getChangeSet().add(changeSet);
|
||||
@@ -113,14 +120,7 @@ public class PendingDrops {
|
||||
|
||||
for (Entry entry : map.values()) {
|
||||
for (ChangeSet changeSet : entry.list) {
|
||||
for (Object change : changeSet.getChangeSetChildren()) {
|
||||
if (change instanceof DropColumn) {
|
||||
DropColumn dropColumn = (DropColumn) change;
|
||||
if (Boolean.TRUE.equals(dropColumn.isWithHistory())) {
|
||||
newModel.registerPendingDropColumn(dropColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
newModel.registerPendingHistoryDropColumns(changeSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,10 +129,16 @@ public class PendingDrops {
|
||||
* Return true if there is an Entry for the given version.
|
||||
*/
|
||||
boolean testContainsEntryFor(MigrationVersion version) {
|
||||
|
||||
return map.containsKey(version.normalised());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Entry for the given version.
|
||||
*/
|
||||
Entry testGetEntryFor(MigrationVersion version) {
|
||||
return map.get(version.normalised());
|
||||
}
|
||||
|
||||
static class Entry {
|
||||
|
||||
final MigrationVersion version;
|
||||
@@ -175,18 +181,79 @@ public class PendingDrops {
|
||||
* Remove the drops that are not suppressForever and return true if that
|
||||
* removed all the changeSets (and there are no suppressForever ones).
|
||||
*/
|
||||
boolean removeDrops() {
|
||||
boolean removeDrops(ChangeSet appliedDrops) {
|
||||
|
||||
Iterator<ChangeSet> iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
ChangeSet next = iterator.next();
|
||||
if (!isSuppressForever(next)) {
|
||||
iterator.remove();
|
||||
removeMatchingChanges(next, appliedDrops);
|
||||
if (next.getChangeSetChildren().isEmpty()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the applied drops from the pending ones matching by table name and column name.
|
||||
*/
|
||||
private void removeMatchingChanges(ChangeSet pendingDrops, ChangeSet appliedDrops) {
|
||||
|
||||
List<Object> pending = pendingDrops.getChangeSetChildren();
|
||||
Iterator<Object> iterator = pending.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Object pendingDrop = iterator.next();
|
||||
if (pendingDrop instanceof DropColumn && dropColumnIn((DropColumn)pendingDrop, appliedDrops)) {
|
||||
iterator.remove();
|
||||
|
||||
} else if (pendingDrop instanceof DropTable && dropTableIn((DropTable)pendingDrop, appliedDrops)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the pendingDrop is contained in the appliedDrops.
|
||||
*/
|
||||
private boolean dropTableIn(DropTable pendingDrop, ChangeSet appliedDrops) {
|
||||
for (Object o : appliedDrops.getChangeSetChildren()) {
|
||||
if (o instanceof DropTable && sameTable(pendingDrop, (DropTable)o)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the pendingDrop is contained in the appliedDrops.
|
||||
*/
|
||||
private boolean dropColumnIn(DropColumn pendingDrop, ChangeSet appliedDrops) {
|
||||
for (Object o : appliedDrops.getChangeSetChildren()) {
|
||||
if (o instanceof DropColumn && sameColumn(pendingDrop, (DropColumn) o)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the DropTable match by table name.
|
||||
*/
|
||||
private boolean sameTable(DropTable pendingDrop, DropTable o) {
|
||||
return pendingDrop.getName().equals(o.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the DropColumns match by table and column name.
|
||||
*/
|
||||
private boolean sameColumn(DropColumn pending, DropColumn o) {
|
||||
return pending.getColumnName().equals(o.getColumnName())
|
||||
&& pending.getTableName().equals(o.getTableName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean isSuppressForever(ChangeSet next) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.avaje.ebean.dbmigration.model;
|
||||
|
||||
import com.avaje.ebean.dbmigration.migration.ChangeSet;
|
||||
import com.avaje.ebean.dbmigration.migration.DropColumn;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -16,12 +17,10 @@ public class EntryTest {
|
||||
assertThat(entry.hasPendingDrops()).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_when_normal() throws Exception {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
entry.add(new ChangeSet());
|
||||
PendingDrops.Entry entry = createEntry(new ChangeSet());
|
||||
|
||||
assertThat(entry.hasPendingDrops()).isTrue();
|
||||
}
|
||||
@@ -29,11 +28,10 @@ public class EntryTest {
|
||||
@Test
|
||||
public void test_when_suppressOnly() throws Exception {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
|
||||
ChangeSet cs = new ChangeSet();
|
||||
cs.setSuppressDropsForever(Boolean.TRUE);
|
||||
entry.add(cs);
|
||||
|
||||
PendingDrops.Entry entry = createEntry(cs);
|
||||
|
||||
assertThat(entry.hasPendingDrops()).isFalse();
|
||||
}
|
||||
@@ -41,12 +39,10 @@ public class EntryTest {
|
||||
@Test
|
||||
public void test_when_both() throws Exception {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
|
||||
ChangeSet cs = new ChangeSet();
|
||||
cs.setSuppressDropsForever(Boolean.TRUE);
|
||||
entry.add(cs);
|
||||
entry.add(new ChangeSet());
|
||||
|
||||
PendingDrops.Entry entry = createEntry(cs, new ChangeSet());
|
||||
|
||||
assertThat(entry.hasPendingDrops()).isTrue();
|
||||
}
|
||||
@@ -60,21 +56,19 @@ public class EntryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_containsSuppressForever_when_not() {
|
||||
public void test_containsSuppressForever_when_notSuppress() {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
entry.add(new ChangeSet());
|
||||
PendingDrops.Entry entry = createEntry(new ChangeSet());
|
||||
|
||||
assertThat(entry.containsSuppressForever()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_containsSuppressForever_when_does() {
|
||||
public void test_containsSuppressForever_when_suppress() {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
ChangeSet cs = new ChangeSet();
|
||||
cs.setSuppressDropsForever(Boolean.TRUE);
|
||||
entry.add(cs);
|
||||
PendingDrops.Entry entry = createEntry(cs);
|
||||
|
||||
assertThat(entry.containsSuppressForever()).isTrue();
|
||||
}
|
||||
@@ -82,45 +76,76 @@ public class EntryTest {
|
||||
@Test
|
||||
public void test_containsSuppressForever_when_mixed() {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
ChangeSet cs = new ChangeSet();
|
||||
cs.setSuppressDropsForever(Boolean.TRUE);
|
||||
entry.add(cs);
|
||||
entry.add(new ChangeSet());
|
||||
|
||||
PendingDrops.Entry entry = createEntry(cs, new ChangeSet());
|
||||
|
||||
assertThat(entry.containsSuppressForever()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_removeDrops_when_empty() {
|
||||
public void test_removeDrops_when_columnsMatch() {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
assertThat(entry.removeDrops()).isTrue();
|
||||
ChangeSet pending = changeSet("one", "two");
|
||||
|
||||
PendingDrops.Entry entry = createEntry(pending);
|
||||
|
||||
assertThat(entry.removeDrops(changeSet("one","two"))).isTrue();
|
||||
assertThat(entry.list).asList().doesNotContain(pending);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_removeDrops_when_notSuppressed() {
|
||||
public void test_removeDrops_when_subset() {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
entry.add(new ChangeSet());
|
||||
assertThat(entry.removeDrops()).isTrue();
|
||||
DropColumn dropColumnTwo = col("two");
|
||||
ChangeSet pending = changeSet("one");
|
||||
pending.getChangeSetChildren().add(dropColumnTwo);
|
||||
|
||||
PendingDrops.Entry entry = createEntry(pending);
|
||||
|
||||
assertThat(entry.removeDrops(changeSet("one"))).isFalse();
|
||||
assertThat(entry.list).asList().containsExactly(pending);
|
||||
assertThat(pending.getChangeSetChildren()).asList().containsExactly(dropColumnTwo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_removeDrops_when_containsSuppressed() {
|
||||
public void test_removeDrops_when_columnsMatch_butSuppressed() {
|
||||
|
||||
ChangeSet pending = changeSet("one", "two");
|
||||
pending.setSuppressDropsForever(Boolean.TRUE);
|
||||
|
||||
PendingDrops.Entry entry = createEntry(pending);
|
||||
|
||||
assertThat(entry.removeDrops(changeSet("one","two"))).isFalse();
|
||||
assertThat(entry.list).asList().contains(pending);
|
||||
assertThat(pending.getChangeSetChildren()).asList().hasSize(2);
|
||||
|
||||
}
|
||||
|
||||
static ChangeSet changeSet(String... colName) {
|
||||
|
||||
PendingDrops.Entry entry = createEntry();
|
||||
entry.add(new ChangeSet());
|
||||
ChangeSet cs = new ChangeSet();
|
||||
cs.setSuppressDropsForever(Boolean.TRUE);
|
||||
entry.add(cs);
|
||||
for (String col : colName) {
|
||||
cs.getChangeSetChildren().add(col(col));
|
||||
}
|
||||
return cs;
|
||||
}
|
||||
|
||||
assertThat(entry.removeDrops()).isFalse();
|
||||
static DropColumn col(String colName) {
|
||||
DropColumn drop = new DropColumn();
|
||||
drop.setColumnName(colName);
|
||||
drop.setTableName("tab");
|
||||
return drop;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PendingDrops.Entry createEntry() {
|
||||
MigrationVersion version = MigrationVersion.parse("1.1");
|
||||
return new PendingDrops.Entry(version);
|
||||
static PendingDrops.Entry createEntry(ChangeSet... pending) {
|
||||
|
||||
PendingDrops.Entry entry = new PendingDrops.Entry(MigrationVersion.parse("1.1"));
|
||||
for (ChangeSet changeSet: pending) {
|
||||
entry.add(changeSet);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
public class MTableTest {
|
||||
|
||||
MTable base() {
|
||||
static MTable base() {
|
||||
MTable table = new MTable("tab");
|
||||
table.addColumn(new MColumn("id","bigint"));
|
||||
table.addColumn(new MColumn("name","varchar(20)"));
|
||||
@@ -23,7 +23,7 @@ public class MTableTest {
|
||||
return table;
|
||||
}
|
||||
|
||||
MTable newTable() {
|
||||
static MTable newTable() {
|
||||
MTable table = new MTable("tab");
|
||||
table.addColumn(new MColumn("id","bigint"));
|
||||
table.addColumn(new MColumn("name","varchar(20)"));
|
||||
@@ -32,7 +32,7 @@ public class MTableTest {
|
||||
return table;
|
||||
}
|
||||
|
||||
MTable newTableAdd2Columns() {
|
||||
static MTable newTableAdd2Columns() {
|
||||
MTable table = new MTable("tab");
|
||||
table.addColumn(new MColumn("id","bigint"));
|
||||
table.addColumn(new MColumn("name","varchar(20)"));
|
||||
@@ -42,7 +42,7 @@ public class MTableTest {
|
||||
return table;
|
||||
}
|
||||
|
||||
MTable newTableModifiedColumn() {
|
||||
static MTable newTableModifiedColumn() {
|
||||
MColumn modCol = new MColumn("name", "varchar(30)");// modified type
|
||||
modCol.setNotnull(true);
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.avaje.ebean.dbmigration.model;
|
||||
|
||||
|
||||
import com.avaje.ebean.dbmigration.migration.Migration;
|
||||
import com.avaje.ebean.dbmigration.migrationreader.MigrationXmlReader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ModelContainerTest {
|
||||
|
||||
@Test
|
||||
public void apply_when_noPendingDrops_then_emptyPending() throws Exception {
|
||||
|
||||
ModelContainer container = new ModelContainer();
|
||||
container.apply(mig("1.0.model.xml"), ver("1.1"));
|
||||
|
||||
assertThat(container.getPendingDrops()).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void apply_when_pendingDrops_then_registeredHistoryTable() throws Exception {
|
||||
|
||||
ModelContainer base = container_1_1();
|
||||
|
||||
MTable table = base.getTable("document");
|
||||
assertThat(table.allHistoryColumns(true)).doesNotContain("zing");
|
||||
|
||||
container_1_1().registerPendingHistoryDropColumns(base);
|
||||
assertThat(table.allHistoryColumns(true)).contains("zing");
|
||||
assertThat(table.allHistoryColumns(false)).doesNotContain("zing");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void apply_when_pendingDropsApplied_then_droppedTableNotInHistory() throws Exception {
|
||||
|
||||
ModelContainer container = container_1_1();
|
||||
container.apply(mig("1.1_2__drops.model.xml"), ver("1.1_2"));
|
||||
|
||||
ModelContainer base = container_1_1();
|
||||
|
||||
container.registerPendingHistoryDropColumns(base);
|
||||
|
||||
assertThat(base.getTable("document").allHistoryColumns(false)).doesNotContain("zing");
|
||||
assertThat(base.getTable("document").allHistoryColumns(true)).doesNotContain("zing");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_when_apply_partial_pendingDrops_then_some_remainder() throws Exception {
|
||||
|
||||
ModelContainer container = container_2_1();
|
||||
container.apply(mig("2.2__drops.model.xml"), ver("2.2"));
|
||||
|
||||
ModelContainer base = container_2_1();
|
||||
|
||||
container.registerPendingHistoryDropColumns(base);
|
||||
|
||||
List<String> normalColumns = base.getTable("document").allHistoryColumns(false);
|
||||
List<String> historyColumns = base.getTable("document").allHistoryColumns(true);
|
||||
|
||||
assertThat(historyColumns).contains("zong","boom","baz","bar");
|
||||
assertThat(normalColumns).doesNotContain("zing","zong","boom","baz","bar");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ModelContainer container_2_1() {
|
||||
ModelContainer container = new ModelContainer();
|
||||
container.apply(mig("2.0.model.xml"), ver("2.0"));
|
||||
container.apply(mig("2.1.model.xml"), ver("2.1"));
|
||||
return container;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ModelContainer container_1_1() {
|
||||
ModelContainer container = new ModelContainer();
|
||||
container.apply(mig("1.0.model.xml"), ver("1.0"));
|
||||
container.apply(mig("1.1.model.xml"), ver("1.1"));
|
||||
return container;
|
||||
}
|
||||
|
||||
private MigrationVersion ver(String version) {
|
||||
return MigrationVersion.parse(version);
|
||||
}
|
||||
|
||||
private Migration mig(String path) {
|
||||
return MigrationXmlReader.read(ModelContainerTest.class.getResourceAsStream(path));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.avaje.ebean.dbmigration.model;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
public class ModelDiffTest {
|
||||
|
||||
@Test
|
||||
public void test_compareTo_with_dropColumnOnHistoryTable_then_historyColumnRegistered() throws Exception {
|
||||
|
||||
ModelContainer base = new ModelContainer();
|
||||
base.addTable(MTableTest.base().setWithHistory(true));
|
||||
|
||||
ModelContainer newModel = new ModelContainer();
|
||||
newModel.addTable(MTableTest.newTable().setWithHistory(true));
|
||||
|
||||
ModelDiff diff = new ModelDiff(base);
|
||||
diff.compareTo(newModel);
|
||||
|
||||
MTable tab = newModel.getTable("tab");
|
||||
|
||||
assertThat(tab.allHistoryColumns(true)).contains("status");
|
||||
assertThat(tab.allColumns()).extracting("name").doesNotContain("status");
|
||||
}
|
||||
}
|
||||
@@ -13,63 +13,80 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class PendingDropsTest {
|
||||
|
||||
@Test
|
||||
public void testAdd() throws Exception {
|
||||
static final MigrationVersion V1_1 = MigrationVersion.parse("1.1");
|
||||
|
||||
ChangeSet cs = new ChangeSet();
|
||||
static final MigrationVersion V1_2 = MigrationVersion.parse("1.2");
|
||||
|
||||
@Test
|
||||
public void test_add() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), cs);
|
||||
pendingDrops.add(V1_1, new ChangeSet());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_add_appliedDropsFor() throws Exception {
|
||||
public void test_appliedDropsFor_when_matchesSome_then_removesMatched() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), new ChangeSet());
|
||||
assertThat(pendingDrops.pendingDrops()).containsExactly("1.1");
|
||||
DropColumn one = col("one");
|
||||
DropColumn two = col("two");
|
||||
pendingDrops.add(V1_1, changeSet(one,two));
|
||||
pendingDrops.add(V1_1, changeSet("three","four"));
|
||||
assertThat(pendingDrops.testGetEntryFor(V1_1).list).asList().hasSize(2);
|
||||
|
||||
pendingDrops.appliedDropsFor(MigrationVersion.parse("1_1"));
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
ChangeSet applied = changeSet("two");
|
||||
applied.setDropsFor("1.1");
|
||||
|
||||
assertThat(pendingDrops.appliedDropsFor(applied)).isFalse();
|
||||
assertThat(pendingDrops.testGetEntryFor(V1_1).list).asList().hasSize(2);
|
||||
assertThat(pendingDrops.testGetEntryFor(V1_1).list.get(0).getChangeSetChildren()).asList().containsExactly(one);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_add_appliedDropsFor_whenSuppressed() throws Exception {
|
||||
public void test_appliedDropsFor_when_matchesAll_then_removesChangeSet() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), newSuppressForeverChangeSet());
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
DropColumn one = col("one");
|
||||
DropColumn two = col("two");
|
||||
pendingDrops.add(V1_1, changeSet(one,two));
|
||||
pendingDrops.add(V1_1, changeSet("three","four"));
|
||||
assertThat(pendingDrops.testGetEntryFor(V1_1).list).asList().hasSize(2);
|
||||
|
||||
pendingDrops.appliedDropsFor(MigrationVersion.parse("1_1"));
|
||||
ChangeSet applied = changeSet("two","one");
|
||||
applied.setDropsFor("1.1");
|
||||
|
||||
assertThat(pendingDrops.appliedDropsFor(applied)).isFalse();
|
||||
assertThat(pendingDrops.testGetEntryFor(V1_1).list).asList().hasSize(1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_add_appliedDropsFor_whenBoth() throws Exception {
|
||||
public void test_appliedDropsFor_when_changeSetSuppressed_isIgnored() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), newSuppressForeverChangeSet());
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), new ChangeSet());
|
||||
assertThat(pendingDrops.pendingDrops()).containsExactly("1.1");
|
||||
DropColumn one = col("one");
|
||||
ChangeSet changeSet = changeSet(one);
|
||||
changeSet.setSuppressDropsForever(true);
|
||||
pendingDrops.add(V1_1, changeSet);
|
||||
|
||||
pendingDrops.appliedDropsFor(MigrationVersion.parse("1_1"));
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
ChangeSet applied = changeSet("one");
|
||||
applied.setDropsFor("1.1");
|
||||
|
||||
assertThat(pendingDrops.appliedDropsFor(applied)).isFalse();
|
||||
assertThat(pendingDrops.testGetEntryFor(V1_1).list).asList().hasSize(1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_pendingDrops() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), new ChangeSet());
|
||||
pendingDrops.add(MigrationVersion.parse("1.2"), new ChangeSet());
|
||||
pendingDrops.add(V1_1, new ChangeSet());
|
||||
pendingDrops.add(V1_2, new ChangeSet());
|
||||
assertThat(pendingDrops.pendingDrops()).containsExactly("1.1", "1.2");
|
||||
}
|
||||
|
||||
@@ -79,10 +96,10 @@ public class PendingDropsTest {
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), newSuppressForeverChangeSet());
|
||||
pendingDrops.add(V1_1, newSuppressForeverChangeSet());
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
|
||||
pendingDrops.add(MigrationVersion.parse("1.2"), new ChangeSet());
|
||||
pendingDrops.add(V1_2, new ChangeSet());
|
||||
assertThat(pendingDrops.pendingDrops()).containsExactly("1.2");
|
||||
}
|
||||
|
||||
@@ -92,29 +109,23 @@ public class PendingDropsTest {
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), newSuppressForeverChangeSet());
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), new ChangeSet());
|
||||
pendingDrops.add(V1_1, newSuppressForeverChangeSet());
|
||||
pendingDrops.add(V1_1, new ChangeSet());
|
||||
assertThat(pendingDrops.pendingDrops()).containsExactly("1.1");
|
||||
|
||||
pendingDrops.add(MigrationVersion.parse("1.2"), new ChangeSet());
|
||||
pendingDrops.add(V1_2, new ChangeSet());
|
||||
assertThat(pendingDrops.pendingDrops()).containsExactly("1.1", "1.2");
|
||||
|
||||
pendingDrops.appliedDropsFor(MigrationVersion.parse("1_1"));
|
||||
assertThat(pendingDrops.pendingDrops()).containsExactly("1.2");
|
||||
|
||||
pendingDrops.appliedDropsFor(MigrationVersion.parse("1_2"));
|
||||
assertThat(pendingDrops.pendingDrops()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMigrationForVersion() throws Exception {
|
||||
public void test_migrationForVersion() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
|
||||
ChangeSet applyDropChangeSet1 = new ChangeSet();
|
||||
ChangeSet applyDropChangeSet2 = new ChangeSet();
|
||||
|
||||
MigrationVersion version = MigrationVersion.parse("1.1");
|
||||
MigrationVersion version = V1_1;
|
||||
pendingDrops.add(version, applyDropChangeSet1);
|
||||
pendingDrops.add(version, applyDropChangeSet2);
|
||||
|
||||
@@ -125,12 +136,12 @@ public class PendingDropsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMigrationForVersion_when_both() throws Exception {
|
||||
public void test_migrationForVersion_when_both() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
|
||||
ChangeSet applyDropChangeSet = new ChangeSet();
|
||||
MigrationVersion version = MigrationVersion.parse("1.1");
|
||||
MigrationVersion version = V1_1;
|
||||
pendingDrops.add(version, newSuppressForeverChangeSet());
|
||||
pendingDrops.add(version, applyDropChangeSet);
|
||||
|
||||
@@ -141,10 +152,10 @@ public class PendingDropsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMigrationForVersion_when_next() throws Exception {
|
||||
public void test_migrationForVersion_when_next() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
MigrationVersion version = MigrationVersion.parse("1.1");
|
||||
MigrationVersion version = V1_1;
|
||||
|
||||
ChangeSet applyDropChangeSet = new ChangeSet();
|
||||
pendingDrops.add(version, newSuppressForeverChangeSet());
|
||||
@@ -157,63 +168,79 @@ public class PendingDropsTest {
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMigrationForVersion_when_next_isSuppressForever() throws Exception {
|
||||
public void test_migrationForVersion_when_next_isSuppressForever() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), newSuppressForeverChangeSet());
|
||||
pendingDrops.add(V1_1, newSuppressForeverChangeSet());
|
||||
pendingDrops.migrationForVersion("next");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMigrationForVersion_when_doesNotExist() throws Exception {
|
||||
public void test_migrationForVersion_when_doesNotExist() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
pendingDrops.migrationForVersion("1_1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMigrationForVersion_when_next_doesNotExist() throws Exception {
|
||||
public void test_migrationForVersion_when_next_doesNotExist() throws Exception {
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
pendingDrops.migrationForVersion("next");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_registerPendingHistoryDropColumns() throws Exception {
|
||||
|
||||
TDModelContainer modelContainer = new TDModelContainer();
|
||||
|
||||
DropColumn drop1 = col("one");
|
||||
drop1.setWithHistory(Boolean.TRUE);
|
||||
|
||||
DropColumn drop2 = col("two");
|
||||
|
||||
ChangeSet changeSet = changeSet(drop1, drop2);
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
pendingDrops.add(V1_1, changeSet);
|
||||
pendingDrops.registerPendingHistoryDropColumns(modelContainer);
|
||||
|
||||
assertThat(modelContainer.drops).containsExactly(changeSet);
|
||||
}
|
||||
|
||||
class TDModelContainer extends ModelContainer {
|
||||
|
||||
List<ChangeSet> drops = new ArrayList<ChangeSet>();
|
||||
|
||||
@Override
|
||||
public void registerPendingHistoryDropColumns(ChangeSet changeSet) {
|
||||
drops.add(changeSet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ChangeSet newSuppressForeverChangeSet() {
|
||||
ChangeSet changeSet = new ChangeSet();
|
||||
changeSet.setSuppressDropsForever(Boolean.TRUE);
|
||||
return changeSet;
|
||||
}
|
||||
|
||||
static ChangeSet changeSet(String... colNames) {
|
||||
return EntryTest.changeSet(colNames);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterPendingHistoryDropColumns() throws Exception {
|
||||
|
||||
TDModelContainer modelContainer = new TDModelContainer();
|
||||
|
||||
|
||||
DropColumn drop1 = new DropColumn();
|
||||
drop1.setWithHistory(Boolean.TRUE);
|
||||
|
||||
DropColumn drop2 = new DropColumn();
|
||||
|
||||
static ChangeSet changeSet(DropColumn... drops) {
|
||||
ChangeSet changeSet = new ChangeSet();
|
||||
changeSet.getChangeSetChildren().add(drop1);
|
||||
changeSet.getChangeSetChildren().add(drop2);
|
||||
|
||||
PendingDrops pendingDrops = new PendingDrops();
|
||||
pendingDrops.add(MigrationVersion.parse("1.1"), changeSet);
|
||||
pendingDrops.registerPendingHistoryDropColumns(modelContainer);
|
||||
|
||||
assertThat(modelContainer.drops).containsExactly(drop1);
|
||||
}
|
||||
|
||||
class TDModelContainer extends ModelContainer {
|
||||
|
||||
List<DropColumn> drops = new ArrayList<DropColumn>();
|
||||
|
||||
@Override
|
||||
public void registerPendingDropColumn(DropColumn dropColumn) {
|
||||
drops.add(dropColumn);
|
||||
for (DropColumn dropColumn : drops) {
|
||||
changeSet.getChangeSetChildren().add(dropColumn);
|
||||
}
|
||||
|
||||
return changeSet;
|
||||
}
|
||||
|
||||
static DropColumn col(String colName) {
|
||||
return EntryTest.col(colName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
|
||||
<createTable name="document" withHistory="true" pkName="pk_document">
|
||||
<column name="id" type="bigint" primaryKey="true" references="document_draft.id" foreignKeyName="fk_document_id"/>
|
||||
<column name="title" type="varchar(255)" unique="uq_document_title"/>
|
||||
<column name="body" type="varchar(255)"/>
|
||||
<column name="zing" type="varchar(255)"/>
|
||||
<column name="zong" type="varchar(255)"/>
|
||||
<column name="version" type="bigint" notnull="true"/>
|
||||
<column name="when_created" type="timestamp" notnull="true"/>
|
||||
<column name="when_modified" type="timestamp" notnull="true"/>
|
||||
</createTable>
|
||||
|
||||
</changeSet>
|
||||
</migration>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
<addColumn tableName="document" withHistory="true">
|
||||
<column name="boom" type="varchar(255)"/>
|
||||
<column name="baz" type="varchar(255)"/>
|
||||
<column name="bar" type="varchar(255)"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
<changeSet type="pendingDrops">
|
||||
<dropColumn columnName="zing" tableName="document" withHistory="true"/>
|
||||
</changeSet>
|
||||
</migration>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply" dropsFor="1.1">
|
||||
<dropColumn columnName="zing" tableName="document" withHistory="true"/>
|
||||
</changeSet>
|
||||
</migration>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
|
||||
<createTable name="document" withHistory="true" pkName="pk_document">
|
||||
<column name="id" type="bigint" primaryKey="true" references="document_draft.id" foreignKeyName="fk_document_id"/>
|
||||
<column name="title" type="varchar(255)" unique="uq_document_title"/>
|
||||
<column name="body" type="varchar(255)"/>
|
||||
<column name="boom" type="varchar(255)"/>
|
||||
<column name="baz" type="varchar(255)"/>
|
||||
<column name="bar" type="varchar(255)"/>
|
||||
<column name="zing" type="varchar(255)"/>
|
||||
<column name="zong" type="varchar(255)"/>
|
||||
<column name="version" type="bigint" notnull="true"/>
|
||||
<column name="when_created" type="timestamp" notnull="true"/>
|
||||
<column name="when_modified" type="timestamp" notnull="true"/>
|
||||
</createTable>
|
||||
|
||||
</changeSet>
|
||||
</migration>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="pendingDrops" suppressDropsForever="true">
|
||||
<dropColumn columnName="boom" tableName="document" withHistory="true"/>
|
||||
<dropColumn columnName="baz" tableName="document" withHistory="true"/>
|
||||
<dropColumn columnName="bar" tableName="document" withHistory="true"/>
|
||||
</changeSet>
|
||||
<changeSet type="pendingDrops">
|
||||
<dropColumn columnName="zing" tableName="document" withHistory="true"/>
|
||||
<dropColumn columnName="zong" tableName="document" withHistory="true"/>
|
||||
</changeSet>
|
||||
</migration>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply" dropsFor="2.1">
|
||||
<dropColumn columnName="zing" tableName="document" withHistory="true"/>
|
||||
</changeSet>
|
||||
</migration>
|
||||
Reference in New Issue
Block a user