diff --git a/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java b/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java index 9e35097..4fcb3e4 100644 --- a/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java +++ b/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java @@ -28,6 +28,8 @@ public class AntTarget extends Task { + "\n\t\tchangeLogTableName=\"[CHANGE LOG TABLE NAME]\"" + "\n\t\tdelimiter=\"[STATEMENT DELIMITER - default ;]\"" + "\n\t\tdelimitertype=\"[STATEMENT DELIMITER TYPE - row or normal, default normal]\"" + + "\n\t\tfake=\"[BOOLEAN - fake migrations]\"" + + "\n\t\tquiet=\"[BOOLEAN - be quieter (omit messages about each statement)]\"" + "\n\t/>" + "\n\n* - Indicates mandatory parameter"; @@ -102,5 +104,14 @@ public void setEncoding(String encoding) { public void setLineEnding(LineEnding lineEnding) { dbDeploy.setLineEnding(lineEnding); } + + public void setQuiet(boolean quiet) { + dbDeploy.setQuiet(quiet); + } + + public void setFake(boolean fake) { + dbDeploy.setFake(fake); + } + } diff --git a/dbdeploy-cli/src/main/java/com/dbdeploy/DbDeployCommandLineParser.java b/dbdeploy-cli/src/main/java/com/dbdeploy/DbDeployCommandLineParser.java index df06818..184da59 100644 --- a/dbdeploy-cli/src/main/java/com/dbdeploy/DbDeployCommandLineParser.java +++ b/dbdeploy-cli/src/main/java/com/dbdeploy/DbDeployCommandLineParser.java @@ -47,11 +47,19 @@ private void copyValuesFromCommandLineToDbDeployBean(DbDeploy dbDeploy, CommandL if (p.getPropertyType().isAssignableFrom(File.class)) { value = new File((String) value); } - - p.getWriteMethod().invoke(dbDeploy, value); + if (p.getPropertyType() == Long.class) { + value = Long.parseLong(value.toString()); + } + if (value != null) { + p.getWriteMethod().invoke(dbDeploy, value); + } } } + if (commandLine.hasOption("fake")) { + dbDeploy.setFake(true); + } + if (commandLine.hasOption("delimitertype")) { dbDeploy.setDelimiterType(DelimiterType.valueOf(commandLine.getOptionValue("delimitertype"))); } @@ -60,6 +68,7 @@ private void copyValuesFromCommandLineToDbDeployBean(DbDeploy dbDeploy, CommandL dbDeploy.setLineEnding(LineEnding.valueOf(commandLine.getOptionValue("lineending"))); } + } catch (Exception e) { throw new RuntimeException(e); } @@ -153,6 +162,17 @@ private Options getOptions() { .withLongOpt("lineending") .create()); + options.addOption(OptionBuilder + .hasArg().withType(Long.class) + .withDescription("The highest numbered delta script to apply") + .withLongOpt("lastChangeToApply") + .create()); + + + options.addOption(OptionBuilder + .withDescription("fake a migration - only make changes to Changelog") + .withLongOpt("fake") + .create()); return options; } diff --git a/dbdeploy-cli/src/test/java/com/dbdeploy/DbDeployCommandLineParserTest.java b/dbdeploy-cli/src/test/java/com/dbdeploy/DbDeployCommandLineParserTest.java index f400a3d..c8cbbb1 100644 --- a/dbdeploy-cli/src/test/java/com/dbdeploy/DbDeployCommandLineParserTest.java +++ b/dbdeploy-cli/src/test/java/com/dbdeploy/DbDeployCommandLineParserTest.java @@ -35,6 +35,8 @@ public void checkAllOfTheOtherFieldsParseOkHere() throws Exception { "--changeLogTableName my-change-log " + "--dbms ora " + "--templatedir /tmp/mytemplates " + + "--fake " + + "--lastChangeToApply 2345 " + "--delimiter \\ --delimitertype row").split(" "), dbDeploy); assertThat(dbDeploy.getUserid(), is("userid")); @@ -48,6 +50,8 @@ public void checkAllOfTheOtherFieldsParseOkHere() throws Exception { assertThat(dbDeploy.getDelimiter(), is("\\")); assertThat(dbDeploy.getDelimiterType(), is(DelimiterType.row)); assertThat(dbDeploy.getTemplatedir().getPath(), is(File.separator + "tmp" + File.separator + "mytemplates")); + assertThat(dbDeploy.getLastChangeToApply(), is(2345L)); + assertThat(dbDeploy.getFake(), is(true)); } @Test diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java b/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java index cad2748..d8ad684 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java @@ -31,6 +31,8 @@ public class DbDeploy { private String delimiter = ";"; private DelimiterType delimiterType = DelimiterType.normal; private File templatedir; + private boolean fake = false; + private boolean quiet = false; public void setDriver(String driver) { this.driver = driver; @@ -80,6 +82,19 @@ public void setLineEnding(LineEnding lineEnding) { this.lineEnding = lineEnding; } + public void setFake(boolean fake) { + this.fake = fake; + } + + public void setQuiet(boolean quiet) { + this.quiet = quiet; + } + + public boolean getQuiet() + { + return this.quiet; + } + public void go() throws Exception { System.err.println(getWelcomeString()); @@ -100,13 +115,15 @@ public void go() throws Exception { if (outputfile != null) { doScriptApplier = new TemplateBasedApplier( new PrintWriter(outputfile, encoding), dbms, - changeLogTableName, delimiter, delimiterType, getTemplatedir()); + changeLogTableName, delimiter, delimiterType, getTemplatedir(), fake); } else { QueryStatementSplitter splitter = new QueryStatementSplitter(); splitter.setDelimiter(getDelimiter()); splitter.setDelimiterType(getDelimiterType()); splitter.setOutputLineEnding(lineEnding); - doScriptApplier = new DirectToDbApplier(queryExecuter, databaseSchemaVersionManager, splitter); + DirectToDbApplier applier = new DirectToDbApplier(queryExecuter, databaseSchemaVersionManager, splitter, fake); + applier.setQuiet(quiet); + doScriptApplier = applier; } ChangeScriptApplier undoScriptApplier = null; @@ -224,4 +241,8 @@ public String getEncoding() { public LineEnding getLineEnding() { return lineEnding; } + + public boolean getFake() { + return fake; + } } diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/appliers/DirectToDbApplier.java b/dbdeploy-core/src/main/java/com/dbdeploy/appliers/DirectToDbApplier.java index 663caca..395b3d0 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/appliers/DirectToDbApplier.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/appliers/DirectToDbApplier.java @@ -14,20 +14,36 @@ public class DirectToDbApplier implements ChangeScriptApplier { private final QueryExecuter queryExecuter; private final DatabaseSchemaVersionManager schemaVersionManager; private final QueryStatementSplitter splitter; + private final boolean fake; + private boolean quiet=false; - public DirectToDbApplier(QueryExecuter queryExecuter, DatabaseSchemaVersionManager schemaVersionManager, QueryStatementSplitter splitter) { + public DirectToDbApplier(QueryExecuter queryExecuter, DatabaseSchemaVersionManager schemaVersionManager, QueryStatementSplitter splitter, + boolean fake) { this.queryExecuter = queryExecuter; this.schemaVersionManager = schemaVersionManager; this.splitter = splitter; + this.fake = fake; + } + + public void setQuiet(boolean quiet) { + this.quiet = quiet; + } + + public boolean getQuiet() { + return this.quiet; } public void apply(List changeScript) { begin(); + String applyType = fake ? "Faking " : "Applying "; + for (ChangeScript script : changeScript) { - System.err.println("Applying " + script + "..."); + System.err.println(applyType + script + "..."); - applyChangeScript(script); + if (! fake) { + applyChangeScript(script); + } insertToSchemaVersionTable(script); commitTransaction(); @@ -48,7 +64,7 @@ protected void applyChangeScript(ChangeScript script) { for (int i = 0; i < statements.size(); i++) { String statement = statements.get(i); try { - if (statements.size() > 1) { + if (statements.size() > 1 && !quiet) { System.err.println(" -> statement " + (i+1) + " of " + statements.size() + "..."); } queryExecuter.execute(statement); diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/appliers/TemplateBasedApplier.java b/dbdeploy-core/src/main/java/com/dbdeploy/appliers/TemplateBasedApplier.java index 98789c2..aa438c9 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/appliers/TemplateBasedApplier.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/appliers/TemplateBasedApplier.java @@ -24,14 +24,17 @@ public class TemplateBasedApplier implements ChangeScriptApplier { private String changeLogTableName; private String delimiter; private DelimiterType delimiterType; + private boolean fake; - public TemplateBasedApplier(Writer writer, String syntax, String changeLogTableName, String delimiter, DelimiterType delimiterType, File templateDirectory) throws IOException { + public TemplateBasedApplier(Writer writer, String syntax, String changeLogTableName, String delimiter, DelimiterType delimiterType, File templateDirectory, + boolean fake) throws IOException { this.syntax = syntax; this.changeLogTableName = changeLogTableName; this.delimiter = delimiter; this.delimiterType = delimiterType; this.writer = writer; this.configuration = new Configuration(); + this.fake = fake; FileTemplateLoader fileTemplateLoader = createFileTemplateLoader(templateDirectory); this.configuration.setTemplateLoader( @@ -74,7 +77,10 @@ public void apply(List changeScripts) { } protected String getTemplateQualifier() { - return "apply"; + if (fake) + return "fake"; + else + return "apply"; } } diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/appliers/UndoTemplateBasedApplier.java b/dbdeploy-core/src/main/java/com/dbdeploy/appliers/UndoTemplateBasedApplier.java index ea4218d..ac2ca9e 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/appliers/UndoTemplateBasedApplier.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/appliers/UndoTemplateBasedApplier.java @@ -4,13 +4,12 @@ import java.io.File; import java.io.IOException; -import java.io.OutputStream; import java.io.Writer; public class UndoTemplateBasedApplier extends TemplateBasedApplier { public UndoTemplateBasedApplier(Writer writer, String syntax, String changeLogTableName, String delimiter, DelimiterType delimiterType, File templateDirectory) throws IOException { - super(writer, syntax, changeLogTableName, delimiter, delimiterType, templateDirectory); + super(writer, syntax, changeLogTableName, delimiter, delimiterType, templateDirectory, false); } @Override diff --git a/dbdeploy-core/src/main/resources/db2_fake.ftl b/dbdeploy-core/src/main/resources/db2_fake.ftl new file mode 100644 index 0000000..7e01ef5 --- /dev/null +++ b/dbdeploy-core/src/main/resources/db2_fake.ftl @@ -0,0 +1,17 @@ +[#ftl] +[#-- @ftlvariable name="changeLogTableName" type="java.lang.String" --] +[#-- @ftlvariable name="delimiter" type="java.lang.String" --] +[#-- @ftlvariable name="separator" type="java.lang.String" --] +[#-- @ftlvariable name="scripts" type="java.util.List" --] +[#list scripts as script] + +-- START CHANGE SCRIPT ${script} + +INSERT INTO ${changeLogTableName} (change_number, complete_dt, applied_by, description) + VALUES (${script.id?c}, CURRENT TIMESTAMP, USER, '${script.description}')${separator}${delimiter} + +COMMIT${separator}${delimiter} + +-- END CHANGE SCRIPT ${script} + +[/#list] diff --git a/dbdeploy-core/src/main/resources/hsql_fake.ftl b/dbdeploy-core/src/main/resources/hsql_fake.ftl new file mode 100644 index 0000000..f0d1677 --- /dev/null +++ b/dbdeploy-core/src/main/resources/hsql_fake.ftl @@ -0,0 +1,17 @@ +[#ftl] +[#-- @ftlvariable name="changeLogTableName" type="java.lang.String" --] +[#-- @ftlvariable name="delimiter" type="java.lang.String" --] +[#-- @ftlvariable name="separator" type="java.lang.String" --] +[#-- @ftlvariable name="scripts" type="java.util.List" --] +[#list scripts as script] + +-- START CHANGE SCRIPT ${script} + +INSERT INTO ${changeLogTableName} (change_number, complete_dt, applied_by, description) + VALUES (${script.id?c}, CURRENT_TIMESTAMP, USER(), '${script.description}')${separator}${delimiter} + +COMMIT${separator}${delimiter} + +-- END CHANGE SCRIPT ${script} + +[/#list] diff --git a/dbdeploy-core/src/main/resources/mssql_fake.ftl b/dbdeploy-core/src/main/resources/mssql_fake.ftl new file mode 100644 index 0000000..6156661 --- /dev/null +++ b/dbdeploy-core/src/main/resources/mssql_fake.ftl @@ -0,0 +1,17 @@ +[#ftl] +[#-- @ftlvariable name="changeLogTableName" type="java.lang.String" --] +[#-- @ftlvariable name="scripts" type="java.util.List" --] +[#list scripts as script] + +-- START CHANGE SCRIPT ${script} + +INSERT INTO ${changeLogTableName} (change_number, complete_dt, applied_by, description) + VALUES (${script.id?c}, getdate(), user_name(), '${script.description}') +GO + +COMMIT +GO + +-- END CHANGE SCRIPT ${script} + +[/#list] \ No newline at end of file diff --git a/dbdeploy-core/src/main/resources/mysql_fake.ftl b/dbdeploy-core/src/main/resources/mysql_fake.ftl new file mode 100644 index 0000000..f0d1677 --- /dev/null +++ b/dbdeploy-core/src/main/resources/mysql_fake.ftl @@ -0,0 +1,17 @@ +[#ftl] +[#-- @ftlvariable name="changeLogTableName" type="java.lang.String" --] +[#-- @ftlvariable name="delimiter" type="java.lang.String" --] +[#-- @ftlvariable name="separator" type="java.lang.String" --] +[#-- @ftlvariable name="scripts" type="java.util.List" --] +[#list scripts as script] + +-- START CHANGE SCRIPT ${script} + +INSERT INTO ${changeLogTableName} (change_number, complete_dt, applied_by, description) + VALUES (${script.id?c}, CURRENT_TIMESTAMP, USER(), '${script.description}')${separator}${delimiter} + +COMMIT${separator}${delimiter} + +-- END CHANGE SCRIPT ${script} + +[/#list] diff --git a/dbdeploy-core/src/main/resources/ora_fake.ftl b/dbdeploy-core/src/main/resources/ora_fake.ftl new file mode 100644 index 0000000..3626579 --- /dev/null +++ b/dbdeploy-core/src/main/resources/ora_fake.ftl @@ -0,0 +1,17 @@ +[#ftl] +[#-- @ftlvariable name="changeLogTableName" type="java.lang.String" --] +[#-- @ftlvariable name="delimiter" type="java.lang.String" --] +[#-- @ftlvariable name="separator" type="java.lang.String" --] +[#-- @ftlvariable name="scripts" type="java.util.List" --] +[#list scripts as script] + +-- START CHANGE SCRIPT ${script} + +INSERT INTO ${changeLogTableName} (change_number, complete_dt, applied_by, description) + VALUES (${script.id?c}, CURRENT_TIMESTAMP, USER, '${script.description}')${separator}${delimiter} + +COMMIT${separator}${delimiter} + +-- END CHANGE SCRIPT ${script} + +[/#list] diff --git a/dbdeploy-core/src/main/resources/pgsql_fake.ftl b/dbdeploy-core/src/main/resources/pgsql_fake.ftl new file mode 100644 index 0000000..f8b7377 --- /dev/null +++ b/dbdeploy-core/src/main/resources/pgsql_fake.ftl @@ -0,0 +1,17 @@ +[#ftl] +[#-- @ftlvariable name="changeLogTableName" type="java.lang.String" --] +[#-- @ftlvariable name="delimiter" type="java.lang.String" --] +[#-- @ftlvariable name="separator" type="java.lang.String" --] +[#-- @ftlvariable name="scripts" type="java.util.List" --] +[#list scripts as script] + +-- START CHANGE SCRIPT ${script} + +INSERT INTO ${changeLogTableName} (change_number, complete_dt, applied_by, description) + VALUES (${script.id?c}, current_timestamp, current_user, '${script.description}')${separator}${delimiter} + +COMMIT${separator}${delimiter} + +-- END CHANGE SCRIPT ${script} + +[/#list] diff --git a/dbdeploy-core/src/main/resources/syb-ase_fake.ftl b/dbdeploy-core/src/main/resources/syb-ase_fake.ftl new file mode 100644 index 0000000..26f1423 --- /dev/null +++ b/dbdeploy-core/src/main/resources/syb-ase_fake.ftl @@ -0,0 +1,18 @@ +[#ftl] +[#-- @ftlvariable name="changeLogTableName" type="java.lang.String" --] +[#-- @ftlvariable name="scripts" type="java.util.List" --] +[#list scripts as script] + +-- START CHANGE SCRIPT ${script} + + +INSERT INTO ${changeLogTableName} (change_number, complete_dt, applied_by, description) + VALUES (${script.id?c}, getdate(), user_name(), '${script.description}') +GO + +COMMIT +GO + +-- END CHANGE SCRIPT ${script} + +[/#list] \ No newline at end of file diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/appliers/DirectToDbApplierTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/appliers/DirectToDbApplierTest.java index 32b4bf8..339cd23 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/appliers/DirectToDbApplierTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/appliers/DirectToDbApplierTest.java @@ -29,7 +29,7 @@ public class DirectToDbApplierTest { @Before public void setUp() { - applier = new DirectToDbApplier(queryExecuter, schemaVersionManager, splitter); + applier = new DirectToDbApplier(queryExecuter, schemaVersionManager, splitter, false); } @Test diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/appliers/FakeDirectToDbApplierTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/appliers/FakeDirectToDbApplierTest.java new file mode 100644 index 0000000..85f615a --- /dev/null +++ b/dbdeploy-core/src/test/java/com/dbdeploy/appliers/FakeDirectToDbApplierTest.java @@ -0,0 +1,51 @@ +package com.dbdeploy.appliers; + +import com.dbdeploy.database.QueryStatementSplitter; +import com.dbdeploy.database.changelog.DatabaseSchemaVersionManager; +import com.dbdeploy.database.changelog.QueryExecuter; +import com.dbdeploy.scripts.ChangeScript; +import com.dbdeploy.scripts.StubChangeScript; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnit44Runner; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnit44Runner.class) +public class FakeDirectToDbApplierTest { + @Mock private QueryExecuter queryExecuter; + @Mock private DatabaseSchemaVersionManager schemaVersionManager; + @Mock private QueryStatementSplitter splitter; + private DirectToDbApplier applier; + + @Before + public void setUp() { + applier = new DirectToDbApplier(queryExecuter, schemaVersionManager, splitter, true); + } + + + @Test + public void shouldNotApplyScripts() throws Exception { + List changes = new ArrayList (); + ChangeScript changeScript = new StubChangeScript(1, "script", "content"); + changes.add(changeScript); + + when(splitter.split("content")).thenReturn(Arrays.asList("content")); + + applier.apply(changes); + + verify(queryExecuter, never()).execute(anyString()); + verify(schemaVersionManager).recordScriptApplied(changeScript); + } + +} + diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/appliers/TemplateBasedApplierTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/appliers/TemplateBasedApplierTest.java index 618bb9f..50ba6bf 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/appliers/TemplateBasedApplierTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/appliers/TemplateBasedApplierTest.java @@ -13,7 +13,7 @@ public class TemplateBasedApplierTest { @Test public void shouldThrowUsageExceptionWhenTemplateNotFound() throws Exception { - TemplateBasedApplier applier = new TemplateBasedApplier(new NullWriter(), "some_complete_rubbish", null, ";", DelimiterType.normal, null); + TemplateBasedApplier applier = new TemplateBasedApplier(new NullWriter(), "some_complete_rubbish", null, ";", DelimiterType.normal, null, false); try { applier.apply(null); Assert.fail("expected exception"); diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/database/ScriptGenerationTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/database/ScriptGenerationTest.java index 58215da..799ebf9 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/database/ScriptGenerationTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/database/ScriptGenerationTest.java @@ -44,7 +44,7 @@ private void runIntegratedTestAndConfirmOutputResults(String syntaxName) throws final StubSchemaManager schemaManager = new StubSchemaManager(); - ChangeScriptApplier applier = new TemplateBasedApplier(writer, syntaxName, "changelog", ";", DelimiterType.normal, null); + ChangeScriptApplier applier = new TemplateBasedApplier(writer, syntaxName, "changelog", ";", DelimiterType.normal, null, false); Controller controller = new Controller(changeScriptRepository, schemaManager, applier, null); controller.processChangeScripts(Long.MAX_VALUE);