From 86ea2d8579319dad550356b10f9c22f355e6f1ef Mon Sep 17 00:00:00 2001 From: unmeshjoshi Date: Wed, 18 Nov 2015 14:57:33 +0530 Subject: [PATCH 1/5] Adding support to run validations on migrations to be applied. Adding support to continue execution on specified exceptions --- .../src/main/java/com/dbdeploy/AntTarget.java | 8 ++ .../20150901299910_create_test_table.sql | 2 + ...102992991_insert_value_into_test_table.sql | 1 + .../20150901299910_create_test_table.sql | 2 + .../20150920220022_valid_script,sql | 1 + .../com/dbdeploy/ChangeScriptValidator.java | 8 ++ .../ChangeScriptValidatorProvider.java | 7 ++ .../main/java/com/dbdeploy/Controller.java | 24 ++++- .../src/main/java/com/dbdeploy/DbDeploy.java | 95 ++++++++++++------- .../dbdeploy/appliers/DirectToDbApplier.java | 43 +++++++-- .../ChangeScriptApplierException.java | 58 +++++++++++ ...ChangeScriptValidationFailedException.java | 18 ++++ .../scripts/ChangeScriptRepository.java | 26 ++++- .../java/com/dbdeploy/ControllerTest.java | 13 +-- .../test/java/com/dbdeploy/DbDeployTest.java | 17 +++- .../appliers/DirectToDbApplierTest.java | 40 +++++++- .../database/ScriptGenerationTest.java | 5 +- .../ChangeScriptValidatorProviderImpl.java | 28 ++++++ .../com/dbdeploy/integration/Database.java | 11 ++- .../DirectToDbIntegrationTest.java | 32 ++++++- 20 files changed, 377 insertions(+), 62 deletions(-) create mode 100644 dbdeploy-core/src/it/db/validation_failing_deltas/20150901299910_create_test_table.sql create mode 100644 dbdeploy-core/src/it/db/validation_failing_deltas/201509102992991_insert_value_into_test_table.sql create mode 100644 dbdeploy-core/src/it/db/validation_passing_deltas/20150901299910_create_test_table.sql create mode 100644 dbdeploy-core/src/it/db/validation_passing_deltas/20150920220022_valid_script,sql create mode 100644 dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidator.java create mode 100644 dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidatorProvider.java create mode 100644 dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptApplierException.java create mode 100644 dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptValidationFailedException.java create mode 100644 dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatorProviderImpl.java diff --git a/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java b/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java index 9e35097..ccbceea 100644 --- a/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java +++ b/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java @@ -102,5 +102,13 @@ public void setEncoding(String encoding) { public void setLineEnding(LineEnding lineEnding) { dbDeploy.setLineEnding(lineEnding); } + + public void setChangeListValidatorProviderClassName(String className) { + dbDeploy.setChangeListValidatorProviderClassName(className); + } + + public void setExceptionsToContinueExecutionOn(String exceptionsCsv) { + dbDeploy.setExceptionsToContinueExecutionOn(exceptionsCsv); + } } diff --git a/dbdeploy-core/src/it/db/validation_failing_deltas/20150901299910_create_test_table.sql b/dbdeploy-core/src/it/db/validation_failing_deltas/20150901299910_create_test_table.sql new file mode 100644 index 0000000..aaeea36 --- /dev/null +++ b/dbdeploy-core/src/it/db/validation_failing_deltas/20150901299910_create_test_table.sql @@ -0,0 +1,2 @@ +CREATE TABLE Test (id INTEGER); + diff --git a/dbdeploy-core/src/it/db/validation_failing_deltas/201509102992991_insert_value_into_test_table.sql b/dbdeploy-core/src/it/db/validation_failing_deltas/201509102992991_insert_value_into_test_table.sql new file mode 100644 index 0000000..4802da7 --- /dev/null +++ b/dbdeploy-core/src/it/db/validation_failing_deltas/201509102992991_insert_value_into_test_table.sql @@ -0,0 +1 @@ +INSERT INTO Test VALUES (6); diff --git a/dbdeploy-core/src/it/db/validation_passing_deltas/20150901299910_create_test_table.sql b/dbdeploy-core/src/it/db/validation_passing_deltas/20150901299910_create_test_table.sql new file mode 100644 index 0000000..aaeea36 --- /dev/null +++ b/dbdeploy-core/src/it/db/validation_passing_deltas/20150901299910_create_test_table.sql @@ -0,0 +1,2 @@ +CREATE TABLE Test (id INTEGER); + diff --git a/dbdeploy-core/src/it/db/validation_passing_deltas/20150920220022_valid_script,sql b/dbdeploy-core/src/it/db/validation_passing_deltas/20150920220022_valid_script,sql new file mode 100644 index 0000000..46fe02d --- /dev/null +++ b/dbdeploy-core/src/it/db/validation_passing_deltas/20150920220022_valid_script,sql @@ -0,0 +1 @@ +INSERT INTO Test VALUES (6); \ No newline at end of file diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidator.java b/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidator.java new file mode 100644 index 0000000..888010d --- /dev/null +++ b/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidator.java @@ -0,0 +1,8 @@ +package com.dbdeploy; + +import com.dbdeploy.exceptions.DbDeployException; +import com.dbdeploy.scripts.ChangeScript; + +public interface ChangeScriptValidator { + boolean validate(ChangeScript changeScript) throws DbDeployException; +} diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidatorProvider.java b/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidatorProvider.java new file mode 100644 index 0000000..6bfc26b --- /dev/null +++ b/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidatorProvider.java @@ -0,0 +1,7 @@ +package com.dbdeploy; + +import java.util.List; + +public interface ChangeScriptValidatorProvider { + public List getValidators(); +} diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/Controller.java b/dbdeploy-core/src/main/java/com/dbdeploy/Controller.java index a76a3f1..ef41056 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/Controller.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/Controller.java @@ -14,17 +14,19 @@ public class Controller { private final AppliedChangesProvider appliedChangesProvider; private final ChangeScriptApplier changeScriptApplier; private final ChangeScriptApplier undoScriptApplier; + private List validators; - private final PrettyPrinter prettyPrinter = new PrettyPrinter(); + private final PrettyPrinter prettyPrinter = new PrettyPrinter(); public Controller(AvailableChangeScriptsProvider availableChangeScriptsProvider, - AppliedChangesProvider appliedChangesProvider, - ChangeScriptApplier changeScriptApplier, ChangeScriptApplier undoScriptApplier) { + AppliedChangesProvider appliedChangesProvider, + ChangeScriptApplier changeScriptApplier, ChangeScriptApplier undoScriptApplier, List validators) { this.availableChangeScriptsProvider = availableChangeScriptsProvider; this.appliedChangesProvider = appliedChangesProvider; this.changeScriptApplier = changeScriptApplier; this.undoScriptApplier = undoScriptApplier; - } + this.validators = validators; + } public void processChangeScripts(Long lastChangeToApply) throws DbDeployException, IOException { if (lastChangeToApply != Long.MAX_VALUE) { @@ -35,6 +37,8 @@ public void processChangeScripts(Long lastChangeToApply) throws DbDeployExceptio List applied = appliedChangesProvider.getAppliedChanges(); List toApply = identifyChangesToApply(lastChangeToApply, scripts, applied); + validateChangeScripts(toApply); + logStatus(scripts, applied, toApply); changeScriptApplier.apply(Collections.unmodifiableList(toApply)); @@ -46,6 +50,18 @@ public void processChangeScripts(Long lastChangeToApply) throws DbDeployExceptio } } + private void validateChangeScripts(List toApply) { + for (ChangeScript changeScript : toApply) { + applyValidations(changeScript); + } + } + + private void applyValidations(ChangeScript changeScript) { + for (ChangeScriptValidator validator : validators) { + validator.validate(changeScript); + } + } + private void logStatus(List scripts, List applied, List toApply) { info("Changes currently applied to database:\n " + prettyPrinter.format(applied)); info("Scripts available:\n " + prettyPrinter.formatChangeScriptList(scripts)); diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java b/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java index cad2748..9bec4f8 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java @@ -14,6 +14,9 @@ import java.io.File; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; public class DbDeploy { private String url; @@ -31,8 +34,10 @@ public class DbDeploy { private String delimiter = ";"; private DelimiterType delimiterType = DelimiterType.normal; private File templatedir; + private String changeListValidatorProviderClassName; + private List exceptionsToContinueExecutionOn = new ArrayList(); - public void setDriver(String driver) { + public void setDriver(String driver) { this.driver = driver; } @@ -80,51 +85,62 @@ public void setLineEnding(LineEnding lineEnding) { this.lineEnding = lineEnding; } - public void go() throws Exception { - System.err.println(getWelcomeString()); + public void go() throws Exception { + System.err.println(getWelcomeString()); - validate(); + validate(); - Class.forName(driver); + Class.forName(driver); - QueryExecuter queryExecuter = new QueryExecuter(url, userid, password); + QueryExecuter queryExecuter = new QueryExecuter(url, userid, password); - DatabaseSchemaVersionManager databaseSchemaVersionManager = - new DatabaseSchemaVersionManager(queryExecuter, changeLogTableName); + DatabaseSchemaVersionManager databaseSchemaVersionManager = + new DatabaseSchemaVersionManager(queryExecuter, changeLogTableName); - ChangeScriptRepository changeScriptRepository = - new ChangeScriptRepository(new DirectoryScanner(encoding).getChangeScriptsForDirectory(scriptdirectory)); + ChangeScriptRepository changeScriptRepository = + new ChangeScriptRepository(new DirectoryScanner(encoding).getChangeScriptsForDirectory(scriptdirectory)); - ChangeScriptApplier doScriptApplier; + ChangeScriptApplier doScriptApplier; - if (outputfile != null) { - doScriptApplier = new TemplateBasedApplier( - new PrintWriter(outputfile, encoding), dbms, - changeLogTableName, delimiter, delimiterType, getTemplatedir()); - } else { - QueryStatementSplitter splitter = new QueryStatementSplitter(); - splitter.setDelimiter(getDelimiter()); - splitter.setDelimiterType(getDelimiterType()); - splitter.setOutputLineEnding(lineEnding); - doScriptApplier = new DirectToDbApplier(queryExecuter, databaseSchemaVersionManager, splitter); - } + if (outputfile != null) { + doScriptApplier = new TemplateBasedApplier( + new PrintWriter(outputfile, encoding), dbms, + changeLogTableName, delimiter, delimiterType, getTemplatedir()); + } else { + QueryStatementSplitter splitter = new QueryStatementSplitter(); + splitter.setDelimiter(getDelimiter()); + splitter.setDelimiterType(getDelimiterType()); + splitter.setOutputLineEnding(lineEnding); + doScriptApplier = new DirectToDbApplier(queryExecuter, databaseSchemaVersionManager, splitter, exceptionsToContinueExecutionOn); - ChangeScriptApplier undoScriptApplier = null; + } - if (undoOutputfile != null) { - undoScriptApplier = new UndoTemplateBasedApplier( - new PrintWriter(undoOutputfile), dbms, changeLogTableName, delimiter, delimiterType, templatedir); + ChangeScriptApplier undoScriptApplier = null; - } + if (undoOutputfile != null) { + undoScriptApplier = new UndoTemplateBasedApplier( + new PrintWriter(undoOutputfile), dbms, changeLogTableName, delimiter, delimiterType, templatedir); - Controller controller = new Controller(changeScriptRepository, databaseSchemaVersionManager, doScriptApplier, undoScriptApplier); + } - controller.processChangeScripts(lastChangeToApply); + List validators = getChangeScriptValidators(); + Controller controller = new Controller(changeScriptRepository, databaseSchemaVersionManager, doScriptApplier, undoScriptApplier, validators); - queryExecuter.close(); - } + controller.processChangeScripts(lastChangeToApply); + + queryExecuter.close(); + } - private void validate() throws UsageException { + private List getChangeScriptValidators() throws InstantiationException, IllegalAccessException, ClassNotFoundException { + List validators = new ArrayList(); + if (changeListValidatorProviderClassName != null && !"".equals(changeListValidatorProviderClassName)) { + ChangeScriptValidatorProvider validatorProvider = (ChangeScriptValidatorProvider) getClass().getClassLoader().loadClass(changeListValidatorProviderClassName).newInstance(); + validators.addAll(validatorProvider.getValidators()); + } + return validators; + } + + private void validate() throws UsageException { checkForRequiredParameter(userid, "userid"); checkForRequiredParameter(driver, "driver"); checkForRequiredParameter(url, "url"); @@ -224,4 +240,19 @@ public String getEncoding() { public LineEnding getLineEnding() { return lineEnding; } + + public void setChangeListValidatorProviderClassName(String changeListValidatorProviderClassName) { + this.changeListValidatorProviderClassName = changeListValidatorProviderClassName; + } + + public void setExceptionsToContinueExecutionOn(String exceptionsCsv) { + StringTokenizer tokenizer = new StringTokenizer(exceptionsCsv, ","); + while(tokenizer.hasMoreTokens()) { + exceptionsToContinueExecutionOn.add(tokenizer.nextToken()); + } + } + + public List getExceptionsToContinueExecutionOn() { + return exceptionsToContinueExecutionOn; + } } 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..72ae864 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/appliers/DirectToDbApplier.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/appliers/DirectToDbApplier.java @@ -4,37 +4,68 @@ import com.dbdeploy.database.QueryStatementSplitter; import com.dbdeploy.database.changelog.DatabaseSchemaVersionManager; import com.dbdeploy.database.changelog.QueryExecuter; +import com.dbdeploy.exceptions.ChangeScriptApplierException; import com.dbdeploy.exceptions.ChangeScriptFailedException; import com.dbdeploy.scripts.ChangeScript; import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; public class DirectToDbApplier implements ChangeScriptApplier { private final QueryExecuter queryExecuter; private final DatabaseSchemaVersionManager schemaVersionManager; private final QueryStatementSplitter splitter; + private List exceptionsToContinueExecutionOn; - public DirectToDbApplier(QueryExecuter queryExecuter, DatabaseSchemaVersionManager schemaVersionManager, QueryStatementSplitter splitter) { + public DirectToDbApplier(QueryExecuter queryExecuter, DatabaseSchemaVersionManager schemaVersionManager, QueryStatementSplitter splitter, List exceptionsToContinueExecutionOn) { this.queryExecuter = queryExecuter; this.schemaVersionManager = schemaVersionManager; this.splitter = splitter; + this.exceptionsToContinueExecutionOn = exceptionsToContinueExecutionOn; } public void apply(List changeScript) { begin(); + List scriptFailedExceptions = new ArrayList(); for (ChangeScript script : changeScript) { System.err.println("Applying " + script + "..."); - applyChangeScript(script); - insertToSchemaVersionTable(script); + try { - commitTransaction(); + apply(script); + + } catch (ChangeScriptFailedException e) { + String errorMessage = e.getCause().getMessage(); + if (!containsMessagePartToIgnore(exceptionsToContinueExecutionOn, errorMessage)) { + throw e; + } + scriptFailedExceptions.add(e); + } + } + + if (!scriptFailedExceptions.isEmpty()) { + throw new ChangeScriptApplierException(scriptFailedExceptions); + } + } + + private boolean containsMessagePartToIgnore(List exceptionsToIgnore, String errorMessage) { + for (String ignoreToken : exceptionsToIgnore) { + if (errorMessage.contains(ignoreToken)) { + return true; + } } + return false; + } + + private void apply(ChangeScript script) { + applyChangeScript(script); + insertToSchemaVersionTable(script); + commitTransaction(); } - public void begin() { + public void begin() { try { queryExecuter.setAutoCommit(false); } catch (SQLException e) { @@ -69,6 +100,4 @@ protected void commitTransaction() { throw new RuntimeException(); } } - - } diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptApplierException.java b/dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptApplierException.java new file mode 100644 index 0000000..4b140d9 --- /dev/null +++ b/dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptApplierException.java @@ -0,0 +1,58 @@ +package com.dbdeploy.exceptions; + +import java.util.List; + +public class ChangeScriptApplierException extends DbDeployException { + List changeScriptExceptions; + + public ChangeScriptApplierException(List changeScriptExceptions) { + this.changeScriptExceptions = changeScriptExceptions; + } + + public List getChangeScriptExceptions() { + return changeScriptExceptions; + } + + @Override + public String getMessage() { + StringBuilder message = new StringBuilder(); + message.append(buildMessage()); + message.append("\n"); + message.append("\n"); + message.append(buildSuggession()); + return message.toString(); + + } + + private String buildSuggession() { + StringBuilder suggession = new StringBuilder(); + suggession.append("If these scripts are already executed, run following command"); + suggession.append("\n"); + suggession.append("gradle -PjdbcUrl= -PjdbcUserName= -PjdbcPassword= -Pmigrations="); + suggession.append(changeScriptNamesCsv()); + suggession.append(" :consultingdb:putMigrationInVersionTable"); + return suggession.toString(); + + } + + private String changeScriptNamesCsv() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < changeScriptExceptions.size(); i++) { + String scriptName = changeScriptExceptions.get(i).getScript().getFile().getName(); + sb.append(scriptName); + if (i != (changeScriptExceptions.size() - 1)) { + sb.append(","); + } + } + return sb.toString(); + } + + private String buildMessage() { + StringBuilder message = new StringBuilder(); + for (ChangeScriptFailedException changeScriptException : changeScriptExceptions) { + message.append(changeScriptException.getMessage()); + message.append("\n"); + } + return message.toString(); + } +} diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptValidationFailedException.java b/dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptValidationFailedException.java new file mode 100644 index 0000000..6ccda57 --- /dev/null +++ b/dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptValidationFailedException.java @@ -0,0 +1,18 @@ +package com.dbdeploy.exceptions; + +public class ChangeScriptValidationFailedException extends DbDeployException { + public ChangeScriptValidationFailedException() { + } + + public ChangeScriptValidationFailedException(String message) { + super(message); + } + + public ChangeScriptValidationFailedException(String message, Throwable cause) { + super(message, cause); + } + + public ChangeScriptValidationFailedException(Throwable cause) { + super(cause); + } +} diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/scripts/ChangeScriptRepository.java b/dbdeploy-core/src/main/java/com/dbdeploy/scripts/ChangeScriptRepository.java index 8498081..4eae18d 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/scripts/ChangeScriptRepository.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/scripts/ChangeScriptRepository.java @@ -1,8 +1,9 @@ package com.dbdeploy.scripts; -import com.dbdeploy.exceptions.DuplicateChangeScriptException; import com.dbdeploy.AvailableChangeScriptsProvider; +import com.dbdeploy.exceptions.DuplicateChangeScriptException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -22,17 +23,32 @@ public ChangeScriptRepository(List scripts) throws DuplicateChange private void checkForDuplicateIds(List scripts) throws DuplicateChangeScriptException { long lastId = -1; - + + List duplicateIds = new ArrayList(); for (ChangeScript script : scripts) { if (script.getId() == lastId) { - throw new DuplicateChangeScriptException("There is more than one change script with number " + lastId); + duplicateIds.add(script.getId()); } - + lastId = script.getId(); } - + if (!duplicateIds.isEmpty()) { + throw new DuplicateChangeScriptException("There is more than one change script with number " + toCSV(duplicateIds)); + } + } + private String toCSV(List c) { + String str = ""; + for (int i = 0; i < c.size(); i++) { + if (i != 0) { + str = str + ","; + } + str = str + c.get(i).toString(); + } + return str; + } + public List getOrderedListOfDoChangeScripts() { return Collections.unmodifiableList(scripts); } diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/ControllerTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/ControllerTest.java index b08438b..377951d 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/ControllerTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/ControllerTest.java @@ -1,13 +1,10 @@ package com.dbdeploy; import com.dbdeploy.scripts.ChangeScript; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import static org.mockito.Mockito.when; import org.mockito.runners.MockitoJUnit44Runner; import java.util.ArrayList; @@ -15,6 +12,10 @@ import java.util.Collections; import java.util.List; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.when; + @RunWith(MockitoJUnit44Runner.class) public class ControllerTest { @@ -27,10 +28,10 @@ public class ControllerTest { private StubChangeScriptApplier applier = new StubChangeScriptApplier(); private StubChangeScriptApplier undoApplier = new StubChangeScriptApplier(); - + private List validators = new ArrayList(); @Before public void setUp() { - controller = new Controller(availableChangeScriptsProvider, appliedChangesProvider, applier, undoApplier); + controller = new Controller(availableChangeScriptsProvider, appliedChangesProvider, applier, undoApplier, validators); change1 = new ChangeScript(1); change2 = new ChangeScript(2); @@ -54,7 +55,7 @@ public void shouldApplyChangeScriptsInOrder() throws Exception { @Test public void shouldNotCrashWhenPassedANullUndoApplier() throws Exception { - controller = new Controller(availableChangeScriptsProvider, appliedChangesProvider, applier, null); + controller = new Controller(availableChangeScriptsProvider, appliedChangesProvider, applier, null, validators); when(appliedChangesProvider.getAppliedChanges()).thenReturn(Collections.emptyList()); diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/DbDeployTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/DbDeployTest.java index c90373a..1db347f 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/DbDeployTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/DbDeployTest.java @@ -1,12 +1,16 @@ package com.dbdeploy; import com.dbdeploy.exceptions.UsageException; -import static org.hamcrest.Matchers.startsWith; -import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import java.io.File; +import java.util.List; + +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; public class DbDeployTest { private final DbDeploy dbDeploy = new DbDeploy(); @@ -65,4 +69,13 @@ public void shouldReportVersionNumberWithoutCrashing() { } + @Test + public void shouldParseExceptionsListCsv() { + dbDeploy.setExceptionsToContinueExecutionOn("ORA-001,ORA-002: duplicate column,ORA-003"); + List exceptionsToIgnore = dbDeploy.getExceptionsToContinueExecutionOn(); + assertEquals(3, exceptionsToIgnore.size()); + assertEquals("ORA-001", exceptionsToIgnore.get(0)); + assertEquals("ORA-002: duplicate column", exceptionsToIgnore.get(1)); + assertEquals("ORA-003", exceptionsToIgnore.get(2)); + } } 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..0a5f223 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/appliers/DirectToDbApplierTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/appliers/DirectToDbApplierTest.java @@ -3,6 +3,7 @@ import com.dbdeploy.database.QueryStatementSplitter; import com.dbdeploy.database.changelog.DatabaseSchemaVersionManager; import com.dbdeploy.database.changelog.QueryExecuter; +import com.dbdeploy.exceptions.ChangeScriptApplierException; import com.dbdeploy.exceptions.ChangeScriptFailedException; import com.dbdeploy.scripts.ChangeScript; import com.dbdeploy.scripts.StubChangeScript; @@ -13,12 +14,16 @@ import org.mockito.runners.MockitoJUnit44Runner; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnit44Runner.class) public class DirectToDbApplierTest { @@ -29,7 +34,8 @@ public class DirectToDbApplierTest { @Before public void setUp() { - applier = new DirectToDbApplier(queryExecuter, schemaVersionManager, splitter); + + applier = new DirectToDbApplier(queryExecuter, schemaVersionManager, splitter, new ArrayList()); } @Test @@ -84,5 +90,33 @@ public void shouldCommitTransactionOnErrrCommitTransaction() throws Exception { verify(queryExecuter).commit(); } + @Test + public void shouldContinueOnErrorIfErrorToIgnoreAreProvided() throws Exception + { + applier = new DirectToDbApplier(queryExecuter, schemaVersionManager, splitter, Arrays.asList("ORA-0001: unique constraint")); + + when(splitter.split("split1; content1")).thenReturn(Arrays.asList("split1", "content1")); + when(splitter.split("content2")).thenReturn(Arrays.asList("content2")); + + ChangeScript script1 = new StubChangeScript(1, "script", "split1; content1"); + ChangeScript script2 = new StubChangeScript(2, "script", "content2"); + + doThrow(new SQLException("ORA-0001: unique constraint")).when(queryExecuter).execute("split1"); + + ChangeScriptApplierException expectedException = null; + try { + applier.apply(Arrays.asList(script1, script2)); + + } catch (ChangeScriptApplierException e) { + expectedException = e; + } + + verify(queryExecuter).execute("split1"); + verify(queryExecuter).execute("content2"); + + ChangeScriptFailedException scriptException = expectedException.getChangeScriptExceptions().get(0); + assertThat(scriptException .getExecutedSql(), is("split1")); + assertThat(scriptException .getScript(), is(script1)); + } } 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..e5c116a 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/database/ScriptGenerationTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/database/ScriptGenerationTest.java @@ -1,6 +1,7 @@ package com.dbdeploy.database; import com.dbdeploy.ChangeScriptApplier; +import com.dbdeploy.ChangeScriptValidator; import com.dbdeploy.Controller; import com.dbdeploy.appliers.TemplateBasedApplier; import com.dbdeploy.database.changelog.DatabaseSchemaVersionManager; @@ -11,6 +12,7 @@ import org.junit.Test; import java.io.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -45,7 +47,8 @@ private void runIntegratedTestAndConfirmOutputResults(String syntaxName) throws final StubSchemaManager schemaManager = new StubSchemaManager(); ChangeScriptApplier applier = new TemplateBasedApplier(writer, syntaxName, "changelog", ";", DelimiterType.normal, null); - Controller controller = new Controller(changeScriptRepository, schemaManager, applier, null); + List validators = new ArrayList(); + Controller controller = new Controller(changeScriptRepository, schemaManager, applier, null, validators); controller.processChangeScripts(Long.MAX_VALUE); diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatorProviderImpl.java b/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatorProviderImpl.java new file mode 100644 index 0000000..f50b1ed --- /dev/null +++ b/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatorProviderImpl.java @@ -0,0 +1,28 @@ +package com.dbdeploy.integration; + + +import com.dbdeploy.ChangeScriptValidator; +import com.dbdeploy.ChangeScriptValidatorProvider; +import com.dbdeploy.exceptions.ChangeScriptValidationFailedException; +import com.dbdeploy.exceptions.DbDeployException; +import com.dbdeploy.scripts.ChangeScript; + +import java.util.ArrayList; +import java.util.List; + +public class ChangeScriptValidatorProviderImpl implements ChangeScriptValidatorProvider { + + public List getValidators() { + List validators = new ArrayList(); + validators.add(new ChangeScriptValidator() { + public boolean validate(ChangeScript changeScript) throws DbDeployException { + String changeScriptName = changeScript.getFile().getName(); + if (!changeScriptName.matches("[0-9]{14}_(.*)")) { + throw new ChangeScriptValidationFailedException("name should start with datetime format yyyyMMddHHmmss"); + } + return Boolean.TRUE; + } + }); + return validators; + } +} \ No newline at end of file diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/integration/Database.java b/dbdeploy-core/src/test/java/com/dbdeploy/integration/Database.java index f822af5..f699f92 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/integration/Database.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/integration/Database.java @@ -21,6 +21,7 @@ public class Database { private static final String DATABASE_DRIVER = "org.hsqldb.jdbcDriver"; private static final String DATABASE_USERNAME = "sa"; private static final String DATABASE_PASSWORD = ""; + private String changeListValidatorProviderClassName; public Database(String databaseName) throws ClassNotFoundException, SQLException { this(databaseName, "changelog"); @@ -40,7 +41,7 @@ private Connection openConnection() throws ClassNotFoundException, SQLException public void createSchemaVersionTable() throws SQLException { execute("CREATE TABLE " + changeLogTableName + " ( " + - " change_number INTEGER NOT NULL, " + + " change_number BIGINT NOT NULL, " + " complete_dt TIMESTAMP NOT NULL, " + " applied_by VARCHAR(100) NOT NULL, " + " description VARCHAR(500) NOT NULL " + @@ -105,4 +106,12 @@ public List getChangelogEntries() throws SchemaVersionTrackingException, S new DatabaseSchemaVersionManager(queryExecuter, changeLogTableName); return schemaVersionManager.getAppliedChanges(); } + + public void setChangeListValidatorProviderClassName(String changeListValidatorProviderClassName) { + this.changeListValidatorProviderClassName = changeListValidatorProviderClassName; + } + + public String getChangeListValidatorProviderClassName() { + return changeListValidatorProviderClassName; + } } diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java index 9290fbd..f924d9a 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java @@ -1,13 +1,17 @@ package com.dbdeploy.integration; import com.dbdeploy.DbDeploy; +import com.dbdeploy.exceptions.ChangeScriptValidationFailedException; import org.junit.Test; import java.io.File; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.fail; public class DirectToDbIntegrationTest { @@ -45,6 +49,32 @@ public void shouldSuccessfullyApplyAValidSetOfDeltasIncludingMutliStatementDelta assertThat(results, hasItems(new Object[] {6}, new Object[] {7})); } + @Test + public void shouldApplyValidateChangeScripts() throws Exception { + Database db = new Database("todb_custaom_validator_passing_test"); + db.createSchemaVersionTable(); + + DbDeploy dbDeploy = new DbDeploy(); + db.applyDatabaseSettingsTo(dbDeploy); + dbDeploy.setChangeListValidatorProviderClassName("com.dbdeploy.integration.ChangeScriptValidatorProviderImpl"); + dbDeploy.setScriptdirectory(findScriptDirectory("src/it/db/validation_passing_deltas")); + dbDeploy.go(); + + assertThat(db.getChangelogEntries(), hasItems(20150920220022L)); + } + + + @Test(expected = ChangeScriptValidationFailedException.class) + public void shouldValidateChangeScriptsToBeAppliedProvidedByValidatorFactory() throws Exception { + Database db = new Database("todb__custom_validator_failing_test"); + db.createSchemaVersionTable(); + + DbDeploy dbDeploy = new DbDeploy(); + db.applyDatabaseSettingsTo(dbDeploy); + dbDeploy.setChangeListValidatorProviderClassName("com.dbdeploy.integration.ChangeScriptValidatorProviderImpl"); + dbDeploy.setScriptdirectory(findScriptDirectory("src/it/db/validation_failing_deltas")); + dbDeploy.go(); + } @Test public void shouldBeAbleToRecoverFromBadScriptsJustByRunningCorrectedScriptsAgain() throws Exception { From f2940afcd387df083dc00db1a1161b13cae0bd1d Mon Sep 17 00:00:00 2001 From: unmeshjoshi Date: Mon, 7 Dec 2015 16:25:32 +0530 Subject: [PATCH 2/5] collecting all ignored exceptions when exception is thrown --- .../dbdeploy/appliers/DirectToDbApplier.java | 4 +- .../appliers/DirectToDbApplierTest.java | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) 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 72ae864..35fa6dc 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/appliers/DirectToDbApplier.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/appliers/DirectToDbApplier.java @@ -38,10 +38,10 @@ public void apply(List changeScript) { } catch (ChangeScriptFailedException e) { String errorMessage = e.getCause().getMessage(); + scriptFailedExceptions.add(e); if (!containsMessagePartToIgnore(exceptionsToContinueExecutionOn, errorMessage)) { - throw e; + break; } - scriptFailedExceptions.add(e); } } 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 0a5f223..d95629f 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/appliers/DirectToDbApplierTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/appliers/DirectToDbApplierTest.java @@ -18,12 +18,14 @@ import java.util.Arrays; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.internal.verification.VerificationModeFactory.times; @RunWith(MockitoJUnit44Runner.class) public class DirectToDbApplierTest { @@ -119,4 +121,62 @@ public void shouldContinueOnErrorIfErrorToIgnoreAreProvided() throws Exception assertThat(scriptException .getScript(), is(script1)); } + @Test + public void shouldStopExecutionIfExceptionIsOtherThanIgnored() throws SQLException { + applier = new DirectToDbApplier(queryExecuter, schemaVersionManager, splitter, Arrays.asList("ORA-0001: unique constraint")); + + when(splitter.split("split1; content1")).thenReturn(Arrays.asList("split1", "content1")); + when(splitter.split("content2")).thenReturn(Arrays.asList("content2")); + + ChangeScript script1 = new StubChangeScript(1, "script", "split1; content1"); + ChangeScript script2 = new StubChangeScript(2, "script", "content2"); + + doThrow(new SQLException("ORA-0002: table or view does not exist")).when(queryExecuter).execute("split1"); + + ChangeScriptApplierException expectedException = null; + try { + applier.apply(Arrays.asList(script1, script2)); + + } catch (ChangeScriptApplierException e) { + expectedException = e; + } + + assertNotNull(expectedException); + verify(queryExecuter).execute("split1"); + verify(queryExecuter, times(0)).execute("content2"); + + } + + + + @Test + public void shouldStopExecutionAndGiveAllPreviousExceptionsIfToIgnoreAreProvided() throws SQLException { + applier = new DirectToDbApplier(queryExecuter, schemaVersionManager, splitter, Arrays.asList("ORA-0001: unique constraint")); + + when(splitter.split("split1; content1")).thenReturn(Arrays.asList("split1", "content1")); + when(splitter.split("content2")).thenReturn(Arrays.asList("content2")); + + ChangeScript script1 = new StubChangeScript(1, "script", "split1; content1"); + ChangeScript script2 = new StubChangeScript(2, "script", "content2"); + + doThrow(new SQLException("ORA-0001: unique constraint")).when(queryExecuter).execute("split1"); + doThrow(new SQLException("ORA-0002: table or view does not exist")).when(queryExecuter).execute("content2"); + + ChangeScriptApplierException expectedException = null; + try { + applier.apply(Arrays.asList(script1, script2)); + + } catch (ChangeScriptApplierException e) { + expectedException = e; + } + + assertNotNull(expectedException); + ChangeScriptFailedException scriptException = expectedException.getChangeScriptExceptions().get(0); + assertThat(scriptException .getExecutedSql(), is("split1")); + assertThat(scriptException.getScript(), is(script1)); + + scriptException = expectedException.getChangeScriptExceptions().get(1); + assertThat(scriptException .getExecutedSql(), is("content2")); + assertThat(scriptException.getScript(), is(script2)); + } } From f8dc290aa2064814f51a9d3fd11fb6fea8b5a14f Mon Sep 17 00:00:00 2001 From: unmeshjoshi Date: Wed, 20 Jan 2016 11:55:30 +0530 Subject: [PATCH 3/5] Adding generic filtering mechanism instead of explicit validations. --- .../src/main/java/com/dbdeploy/AntTarget.java | 20 ++++++++++-- .../java/com/dbdeploy/ChangeScriptFilter.java | 10 ++++++ .../ChangeScriptValidatorProvider.java | 7 ---- .../main/java/com/dbdeploy/Controller.java | 32 +++++++++++-------- .../src/main/java/com/dbdeploy/DbDeploy.java | 18 +++-------- .../com/dbdeploy/ChangeScriptValidator.java | 0 .../ChangeScriptValidatorProvider.java | 11 +++++++ .../java/com/dbdeploy/ControllerTest.java | 10 ++++-- .../database/ScriptGenerationTest.java | 18 ++++++++--- ...java => ChangeScriptValidatingFilter.java} | 20 ++++++++++-- .../DirectToDbIntegrationTest.java | 4 +-- 11 files changed, 100 insertions(+), 50 deletions(-) create mode 100644 dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptFilter.java delete mode 100644 dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidatorProvider.java rename dbdeploy-core/src/{main => test}/java/com/dbdeploy/ChangeScriptValidator.java (100%) create mode 100644 dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidatorProvider.java rename dbdeploy-core/src/test/java/com/dbdeploy/integration/{ChangeScriptValidatorProviderImpl.java => ChangeScriptValidatingFilter.java} (59%) diff --git a/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java b/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java index ccbceea..1fa0679 100644 --- a/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java +++ b/dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java @@ -3,10 +3,12 @@ import com.dbdeploy.database.DelimiterType; import com.dbdeploy.database.LineEnding; import com.dbdeploy.exceptions.UsageException; +import com.dbdeploy.scripts.ChangeScript; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import java.io.File; +import java.util.List; public class AntTarget extends Task { private DbDeploy dbDeploy = new DbDeploy(); @@ -103,12 +105,26 @@ public void setLineEnding(LineEnding lineEnding) { dbDeploy.setLineEnding(lineEnding); } - public void setChangeListValidatorProviderClassName(String className) { - dbDeploy.setChangeListValidatorProviderClassName(className); + public void setChangeScriptFilterClassName(String className) { + ChangeScriptFilter filter = newChangeSciptFilter(className); + dbDeploy.setChangeScriptFilter(filter); } public void setExceptionsToContinueExecutionOn(String exceptionsCsv) { dbDeploy.setExceptionsToContinueExecutionOn(exceptionsCsv); } + + private ChangeScriptFilter newChangeSciptFilter(String filterClassName) { + try { + ChangeScriptFilter filter = null; + if (filterClassName != null && !"".equals(filterClassName)) { + filter = (ChangeScriptFilter) getClass().getClassLoader().loadClass(filterClassName).newInstance(); + } + return filter; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptFilter.java b/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptFilter.java new file mode 100644 index 0000000..83fa496 --- /dev/null +++ b/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptFilter.java @@ -0,0 +1,10 @@ +package com.dbdeploy; + +import com.dbdeploy.scripts.ChangeScript; + +import java.util.List; + +public interface ChangeScriptFilter { + + public void process(List changeScripts); +} diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidatorProvider.java b/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidatorProvider.java deleted file mode 100644 index 6bfc26b..0000000 --- a/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidatorProvider.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dbdeploy; - -import java.util.List; - -public interface ChangeScriptValidatorProvider { - public List getValidators(); -} diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/Controller.java b/dbdeploy-core/src/main/java/com/dbdeploy/Controller.java index ef41056..20d401b 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/Controller.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/Controller.java @@ -14,21 +14,32 @@ public class Controller { private final AppliedChangesProvider appliedChangesProvider; private final ChangeScriptApplier changeScriptApplier; private final ChangeScriptApplier undoScriptApplier; - private List validators; + private ChangeScriptFilter changeScriptFilter; private final PrettyPrinter prettyPrinter = new PrettyPrinter(); public Controller(AvailableChangeScriptsProvider availableChangeScriptsProvider, AppliedChangesProvider appliedChangesProvider, - ChangeScriptApplier changeScriptApplier, ChangeScriptApplier undoScriptApplier, List validators) { + ChangeScriptApplier changeScriptApplier, ChangeScriptApplier undoScriptApplier, ChangeScriptFilter changeScriptFilter) { this.availableChangeScriptsProvider = availableChangeScriptsProvider; this.appliedChangesProvider = appliedChangesProvider; this.changeScriptApplier = changeScriptApplier; this.undoScriptApplier = undoScriptApplier; - this.validators = validators; + this.changeScriptFilter = maskNull(changeScriptFilter); } - public void processChangeScripts(Long lastChangeToApply) throws DbDeployException, IOException { + private ChangeScriptFilter maskNull(ChangeScriptFilter changeScriptFilter) { + if (changeScriptFilter == null) { + return new ChangeScriptFilter() { + public void process(List changeScripts) { + //no op + } + }; + } + return changeScriptFilter; + } + + public void processChangeScripts(Long lastChangeToApply) throws DbDeployException, IOException { if (lastChangeToApply != Long.MAX_VALUE) { info("Only applying changes up and including change script #" + lastChangeToApply); } @@ -37,7 +48,7 @@ public void processChangeScripts(Long lastChangeToApply) throws DbDeployExceptio List applied = appliedChangesProvider.getAppliedChanges(); List toApply = identifyChangesToApply(lastChangeToApply, scripts, applied); - validateChangeScripts(toApply); + applyFilter(toApply); logStatus(scripts, applied, toApply); @@ -50,17 +61,10 @@ public void processChangeScripts(Long lastChangeToApply) throws DbDeployExceptio } } - private void validateChangeScripts(List toApply) { - for (ChangeScript changeScript : toApply) { - applyValidations(changeScript); - } + private void applyFilter(List toApply) { + changeScriptFilter.process(toApply); } - private void applyValidations(ChangeScript changeScript) { - for (ChangeScriptValidator validator : validators) { - validator.validate(changeScript); - } - } private void logStatus(List scripts, List applied, List toApply) { info("Changes currently applied to database:\n " + prettyPrinter.format(applied)); diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java b/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java index 9bec4f8..e2eddc1 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java +++ b/dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java @@ -34,7 +34,7 @@ public class DbDeploy { private String delimiter = ";"; private DelimiterType delimiterType = DelimiterType.normal; private File templatedir; - private String changeListValidatorProviderClassName; + private ChangeScriptFilter changeScriptFilter; private List exceptionsToContinueExecutionOn = new ArrayList(); public void setDriver(String driver) { @@ -123,23 +123,13 @@ public void go() throws Exception { } - List validators = getChangeScriptValidators(); - Controller controller = new Controller(changeScriptRepository, databaseSchemaVersionManager, doScriptApplier, undoScriptApplier, validators); + Controller controller = new Controller(changeScriptRepository, databaseSchemaVersionManager, doScriptApplier, undoScriptApplier, changeScriptFilter); controller.processChangeScripts(lastChangeToApply); queryExecuter.close(); } - private List getChangeScriptValidators() throws InstantiationException, IllegalAccessException, ClassNotFoundException { - List validators = new ArrayList(); - if (changeListValidatorProviderClassName != null && !"".equals(changeListValidatorProviderClassName)) { - ChangeScriptValidatorProvider validatorProvider = (ChangeScriptValidatorProvider) getClass().getClassLoader().loadClass(changeListValidatorProviderClassName).newInstance(); - validators.addAll(validatorProvider.getValidators()); - } - return validators; - } - private void validate() throws UsageException { checkForRequiredParameter(userid, "userid"); checkForRequiredParameter(driver, "driver"); @@ -241,8 +231,8 @@ public LineEnding getLineEnding() { return lineEnding; } - public void setChangeListValidatorProviderClassName(String changeListValidatorProviderClassName) { - this.changeListValidatorProviderClassName = changeListValidatorProviderClassName; + public void setChangeScriptFilter(ChangeScriptFilter changeScriptFilter) { + this.changeScriptFilter = changeScriptFilter; } public void setExceptionsToContinueExecutionOn(String exceptionsCsv) { diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidator.java b/dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidator.java similarity index 100% rename from dbdeploy-core/src/main/java/com/dbdeploy/ChangeScriptValidator.java rename to dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidator.java diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidatorProvider.java b/dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidatorProvider.java new file mode 100644 index 0000000..1070e72 --- /dev/null +++ b/dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidatorProvider.java @@ -0,0 +1,11 @@ +package com.dbdeploy; + +import com.dbdeploy.scripts.ChangeScript; + +import java.util.List; + +public class ChangeScriptValidatorProvider implements ChangeScriptFilter { + public void process(List changeScripts) { + + } +} diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/ControllerTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/ControllerTest.java index 377951d..71daa2c 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/ControllerTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/ControllerTest.java @@ -28,10 +28,14 @@ public class ControllerTest { private StubChangeScriptApplier applier = new StubChangeScriptApplier(); private StubChangeScriptApplier undoApplier = new StubChangeScriptApplier(); - private List validators = new ArrayList(); + private ChangeScriptFilter changeScriptFilter = new ChangeScriptFilter() { + public void process(List changeScripts) { + //noop + } + }; @Before public void setUp() { - controller = new Controller(availableChangeScriptsProvider, appliedChangesProvider, applier, undoApplier, validators); + controller = new Controller(availableChangeScriptsProvider, appliedChangesProvider, applier, undoApplier, changeScriptFilter); change1 = new ChangeScript(1); change2 = new ChangeScript(2); @@ -55,7 +59,7 @@ public void shouldApplyChangeScriptsInOrder() throws Exception { @Test public void shouldNotCrashWhenPassedANullUndoApplier() throws Exception { - controller = new Controller(availableChangeScriptsProvider, appliedChangesProvider, applier, null, validators); + controller = new Controller(availableChangeScriptsProvider, appliedChangesProvider, applier, null, changeScriptFilter); when(appliedChangesProvider.getAppliedChanges()).thenReturn(Collections.emptyList()); 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 e5c116a..091a25b 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/database/ScriptGenerationTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/database/ScriptGenerationTest.java @@ -1,8 +1,8 @@ package com.dbdeploy.database; import com.dbdeploy.ChangeScriptApplier; -import com.dbdeploy.ChangeScriptValidator; import com.dbdeploy.Controller; +import com.dbdeploy.ChangeScriptFilter; import com.dbdeploy.appliers.TemplateBasedApplier; import com.dbdeploy.database.changelog.DatabaseSchemaVersionManager; import com.dbdeploy.exceptions.SchemaVersionTrackingException; @@ -11,8 +11,12 @@ import com.dbdeploy.scripts.StubChangeScript; import org.junit.Test; -import java.io.*; -import java.util.ArrayList; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -47,8 +51,12 @@ private void runIntegratedTestAndConfirmOutputResults(String syntaxName) throws final StubSchemaManager schemaManager = new StubSchemaManager(); ChangeScriptApplier applier = new TemplateBasedApplier(writer, syntaxName, "changelog", ";", DelimiterType.normal, null); - List validators = new ArrayList(); - Controller controller = new Controller(changeScriptRepository, schemaManager, applier, null, validators); + ChangeScriptFilter chain = new ChangeScriptFilter() { + public void process(List changeScripts) { + + } + }; + Controller controller = new Controller(changeScriptRepository, schemaManager, applier, null, chain); controller.processChangeScripts(Long.MAX_VALUE); diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatorProviderImpl.java b/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatingFilter.java similarity index 59% rename from dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatorProviderImpl.java rename to dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatingFilter.java index f50b1ed..46bbed6 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatorProviderImpl.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatingFilter.java @@ -2,7 +2,7 @@ import com.dbdeploy.ChangeScriptValidator; -import com.dbdeploy.ChangeScriptValidatorProvider; +import com.dbdeploy.ChangeScriptFilter; import com.dbdeploy.exceptions.ChangeScriptValidationFailedException; import com.dbdeploy.exceptions.DbDeployException; import com.dbdeploy.scripts.ChangeScript; @@ -10,9 +10,9 @@ import java.util.ArrayList; import java.util.List; -public class ChangeScriptValidatorProviderImpl implements ChangeScriptValidatorProvider { +public class ChangeScriptValidatingFilter implements ChangeScriptFilter { - public List getValidators() { + private List getValidators() { List validators = new ArrayList(); validators.add(new ChangeScriptValidator() { public boolean validate(ChangeScript changeScript) throws DbDeployException { @@ -25,4 +25,18 @@ public boolean validate(ChangeScript changeScript) throws DbDeployException { }); return validators; } + + public void process(List changeScripts) { + for (ChangeScript changeScript : changeScripts) { + applyValidations(changeScript); + } + } + + private void applyValidations(ChangeScript changeScript) { + List validators = getValidators(); + for (ChangeScriptValidator validator : validators) { + validator.validate(changeScript); + } + + } } \ No newline at end of file diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java index f924d9a..a0b3c62 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java @@ -56,7 +56,7 @@ public void shouldApplyValidateChangeScripts() throws Exception { DbDeploy dbDeploy = new DbDeploy(); db.applyDatabaseSettingsTo(dbDeploy); - dbDeploy.setChangeListValidatorProviderClassName("com.dbdeploy.integration.ChangeScriptValidatorProviderImpl"); + dbDeploy.setChangeScriptFilter(new ChangeScriptValidatingFilter()); dbDeploy.setScriptdirectory(findScriptDirectory("src/it/db/validation_passing_deltas")); dbDeploy.go(); @@ -71,7 +71,7 @@ public void shouldValidateChangeScriptsToBeAppliedProvidedByValidatorFactory() t DbDeploy dbDeploy = new DbDeploy(); db.applyDatabaseSettingsTo(dbDeploy); - dbDeploy.setChangeListValidatorProviderClassName("com.dbdeploy.integration.ChangeScriptValidatorProviderImpl"); + dbDeploy.setChangeScriptFilter(new ChangeScriptValidatingFilter()); dbDeploy.setScriptdirectory(findScriptDirectory("src/it/db/validation_failing_deltas")); dbDeploy.go(); } From 9ec1138ab38a42ff11ad3a512d7f38f09238eda0 Mon Sep 17 00:00:00 2001 From: unmeshjoshi Date: Thu, 11 Feb 2016 15:55:50 +0530 Subject: [PATCH 4/5] moving exception to test --- .../com/dbdeploy}/ChangeScriptValidationFailedException.java | 4 +++- .../dbdeploy/integration/ChangeScriptValidatingFilter.java | 2 +- .../com/dbdeploy/integration/DirectToDbIntegrationTest.java | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) rename dbdeploy-core/src/{main/java/com/dbdeploy/exceptions => test/java/com/dbdeploy}/ChangeScriptValidationFailedException.java (86%) diff --git a/dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptValidationFailedException.java b/dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidationFailedException.java similarity index 86% rename from dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptValidationFailedException.java rename to dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidationFailedException.java index 6ccda57..d737ca8 100644 --- a/dbdeploy-core/src/main/java/com/dbdeploy/exceptions/ChangeScriptValidationFailedException.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/ChangeScriptValidationFailedException.java @@ -1,4 +1,6 @@ -package com.dbdeploy.exceptions; +package com.dbdeploy; + +import com.dbdeploy.exceptions.DbDeployException; public class ChangeScriptValidationFailedException extends DbDeployException { public ChangeScriptValidationFailedException() { diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatingFilter.java b/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatingFilter.java index 46bbed6..fb4180d 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatingFilter.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/integration/ChangeScriptValidatingFilter.java @@ -3,7 +3,7 @@ import com.dbdeploy.ChangeScriptValidator; import com.dbdeploy.ChangeScriptFilter; -import com.dbdeploy.exceptions.ChangeScriptValidationFailedException; +import com.dbdeploy.ChangeScriptValidationFailedException; import com.dbdeploy.exceptions.DbDeployException; import com.dbdeploy.scripts.ChangeScript; diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java b/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java index a0b3c62..50b3ec6 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/integration/DirectToDbIntegrationTest.java @@ -1,7 +1,7 @@ package com.dbdeploy.integration; import com.dbdeploy.DbDeploy; -import com.dbdeploy.exceptions.ChangeScriptValidationFailedException; +import com.dbdeploy.ChangeScriptValidationFailedException; import org.junit.Test; import java.io.File; From faa1c1530931ee1d8c72f78aa574ad1f81977525 Mon Sep 17 00:00:00 2001 From: unmeshjoshi Date: Thu, 11 Feb 2016 15:58:56 +0530 Subject: [PATCH 5/5] removing unused code --- .../src/test/java/com/dbdeploy/integration/Database.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/dbdeploy-core/src/test/java/com/dbdeploy/integration/Database.java b/dbdeploy-core/src/test/java/com/dbdeploy/integration/Database.java index f699f92..bd49a7d 100644 --- a/dbdeploy-core/src/test/java/com/dbdeploy/integration/Database.java +++ b/dbdeploy-core/src/test/java/com/dbdeploy/integration/Database.java @@ -21,7 +21,6 @@ public class Database { private static final String DATABASE_DRIVER = "org.hsqldb.jdbcDriver"; private static final String DATABASE_USERNAME = "sa"; private static final String DATABASE_PASSWORD = ""; - private String changeListValidatorProviderClassName; public Database(String databaseName) throws ClassNotFoundException, SQLException { this(databaseName, "changelog"); @@ -106,12 +105,4 @@ public List getChangelogEntries() throws SchemaVersionTrackingException, S new DatabaseSchemaVersionManager(queryExecuter, changeLogTableName); return schemaVersionManager.getAppliedChanges(); } - - public void setChangeListValidatorProviderClassName(String changeListValidatorProviderClassName) { - this.changeListValidatorProviderClassName = changeListValidatorProviderClassName; - } - - public String getChangeListValidatorProviderClassName() { - return changeListValidatorProviderClassName; - } }