diff --git a/src/main/java/com/avaje/ebean/dbmigration/DbMigration.java b/src/main/java/com/avaje/ebean/dbmigration/DbMigration.java index 78f14c263..69a9c047f 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/DbMigration.java +++ b/src/main/java/com/avaje/ebean/dbmigration/DbMigration.java @@ -220,6 +220,9 @@ public class DbMigration { } } + /** + * Generate the diff migration. + */ private void generateDiff(Request request) throws IOException { List 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(); } } diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/CurrentModel.java b/src/main/java/com/avaje/ebean/dbmigration/model/CurrentModel.java index 645007ff1..b7e06e98a 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/CurrentModel.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/CurrentModel.java @@ -159,12 +159,7 @@ public class CurrentModel { ModelDiff diff = new ModelDiff(); diff.compareTo(model); - List applyChanges = diff.getApplyChanges(); - - // put the changes into a ChangeSet - ChangeSet applyChangeSet = new ChangeSet(); - applyChangeSet.getChangeSetChildren().addAll(applyChanges); - return applyChangeSet; + return diff.getApplyChangeSet(); } } diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java b/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java index e43030d4c..343d8f65b 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java @@ -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 allHistoryColumns(boolean includeDropped) { diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/ModelContainer.java b/src/main/java/com/avaje/ebean/dbmigration/model/ModelContainer.java index 359538d76..e3a41fdc2 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/ModelContainer.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/ModelContainer.java @@ -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 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) { diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/ModelDiff.java b/src/main/java/com/avaje/ebean/dbmigration/model/ModelDiff.java index 1f7d42486..f851143b2 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/ModelDiff.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/ModelDiff.java @@ -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 getApplyChanges() { + List getApplyChanges() { return applyChanges; } /** * Return the list of 'drop' changes. */ - public List getDropChanges() { + List 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) { diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/PendingDrops.java b/src/main/java/com/avaje/ebean/dbmigration/model/PendingDrops.java index 27e064ec7..cb4235f92 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/PendingDrops.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/PendingDrops.java @@ -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 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 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 pending = pendingDrops.getChangeSetChildren(); + Iterator 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) { diff --git a/src/test/java/com/avaje/ebean/dbmigration/model/EntryTest.java b/src/test/java/com/avaje/ebean/dbmigration/model/EntryTest.java index 4ccdcd31e..46f7eeb57 100644 --- a/src/test/java/com/avaje/ebean/dbmigration/model/EntryTest.java +++ b/src/test/java/com/avaje/ebean/dbmigration/model/EntryTest.java @@ -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; } } \ No newline at end of file diff --git a/src/test/java/com/avaje/ebean/dbmigration/model/MTableTest.java b/src/test/java/com/avaje/ebean/dbmigration/model/MTableTest.java index d327f7a74..794461e46 100644 --- a/src/test/java/com/avaje/ebean/dbmigration/model/MTableTest.java +++ b/src/test/java/com/avaje/ebean/dbmigration/model/MTableTest.java @@ -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); diff --git a/src/test/java/com/avaje/ebean/dbmigration/model/ModelContainerTest.java b/src/test/java/com/avaje/ebean/dbmigration/model/ModelContainerTest.java new file mode 100644 index 000000000..a56df0111 --- /dev/null +++ b/src/test/java/com/avaje/ebean/dbmigration/model/ModelContainerTest.java @@ -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 normalColumns = base.getTable("document").allHistoryColumns(false); + List 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)); + } +} \ No newline at end of file diff --git a/src/test/java/com/avaje/ebean/dbmigration/model/ModelDiffTest.java b/src/test/java/com/avaje/ebean/dbmigration/model/ModelDiffTest.java new file mode 100644 index 000000000..aa6638f7f --- /dev/null +++ b/src/test/java/com/avaje/ebean/dbmigration/model/ModelDiffTest.java @@ -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"); + } +} \ No newline at end of file diff --git a/src/test/java/com/avaje/ebean/dbmigration/model/PendingDropsTest.java b/src/test/java/com/avaje/ebean/dbmigration/model/PendingDropsTest.java index 75dfee6ca..3411fcc86 100644 --- a/src/test/java/com/avaje/ebean/dbmigration/model/PendingDropsTest.java +++ b/src/test/java/com/avaje/ebean/dbmigration/model/PendingDropsTest.java @@ -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 drops = new ArrayList(); + + @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 drops = new ArrayList(); - - @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); + } + } \ No newline at end of file diff --git a/src/test/resources/com/avaje/ebean/dbmigration/model/1.0.model.xml b/src/test/resources/com/avaje/ebean/dbmigration/model/1.0.model.xml new file mode 100644 index 000000000..59cf28103 --- /dev/null +++ b/src/test/resources/com/avaje/ebean/dbmigration/model/1.0.model.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/com/avaje/ebean/dbmigration/model/1.1.model.xml b/src/test/resources/com/avaje/ebean/dbmigration/model/1.1.model.xml new file mode 100644 index 000000000..b86fcaf19 --- /dev/null +++ b/src/test/resources/com/avaje/ebean/dbmigration/model/1.1.model.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/com/avaje/ebean/dbmigration/model/1.1_2__drops.model.xml b/src/test/resources/com/avaje/ebean/dbmigration/model/1.1_2__drops.model.xml new file mode 100644 index 000000000..9e38613f9 --- /dev/null +++ b/src/test/resources/com/avaje/ebean/dbmigration/model/1.1_2__drops.model.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/test/resources/com/avaje/ebean/dbmigration/model/2.0.model.xml b/src/test/resources/com/avaje/ebean/dbmigration/model/2.0.model.xml new file mode 100644 index 000000000..3d9cab3bf --- /dev/null +++ b/src/test/resources/com/avaje/ebean/dbmigration/model/2.0.model.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/com/avaje/ebean/dbmigration/model/2.1.model.xml b/src/test/resources/com/avaje/ebean/dbmigration/model/2.1.model.xml new file mode 100644 index 000000000..dcc34d9c8 --- /dev/null +++ b/src/test/resources/com/avaje/ebean/dbmigration/model/2.1.model.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/com/avaje/ebean/dbmigration/model/2.2__drops.model.xml b/src/test/resources/com/avaje/ebean/dbmigration/model/2.2__drops.model.xml new file mode 100644 index 000000000..ecf60135f --- /dev/null +++ b/src/test/resources/com/avaje/ebean/dbmigration/model/2.2__drops.model.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file