diff --git a/flyway-ant/src/main/java/org/flywaydb/ant/AbstractFlywayTask.java b/flyway-ant/src/main/java/org/flywaydb/ant/AbstractFlywayTask.java index 1951d82a31..1cb3e42f38 100644 --- a/flyway-ant/src/main/java/org/flywaydb/ant/AbstractFlywayTask.java +++ b/flyway-ant/src/main/java/org/flywaydb/ant/AbstractFlywayTask.java @@ -193,6 +193,15 @@ public void setCallbacks(String callbacks) { this.callbacks = StringUtils.tokenizeToStringArray(callbacks, ","); } + /** + * @param skipDefaultCallbacks Whether built-int callbacks should be skipped. + * If true, only custom callbacks are used.

(default: false)

+ *
Also configurable with Ant Property: ${flyway.skipDefaultCallbacks} + */ + public void setSkipDefaultCallbacks(boolean skipDefaultCallbacks) { + flyway.setSkipDefaultCallbacks(skipDefaultCallbacks); + } + /** * @param table

The name of the schema metadata table that will be used by Flyway.

By default (single-schema mode) the * metadata table is placed in the default schema for the connection provided by the datasource.

When the diff --git a/flyway-commandline/src/main/assembly/flyway.conf b/flyway-commandline/src/main/assembly/flyway.conf index 6ca9ad0702..091e47d1a3 100644 --- a/flyway-commandline/src/main/assembly/flyway.conf +++ b/flyway-commandline/src/main/assembly/flyway.conf @@ -154,3 +154,8 @@ flyway.url= # This allows you to tie in custom code and logic to the Flyway lifecycle notifications (default: empty). # Set this to a comma-separated list of fully qualified FlywayCallback class name implementations # flyway.callbacks= + +# If set to true, default built-in callbacks (sql) are skipped and only custom callback as +# defined by 'flyway.callbacks' are used. (default: false) +# flyway.skipDefaultResolvers= + diff --git a/flyway-commandline/src/main/java/org/flywaydb/commandline/Main.java b/flyway-commandline/src/main/java/org/flywaydb/commandline/Main.java index 69787be585..231b8429ee 100644 --- a/flyway-commandline/src/main/java/org/flywaydb/commandline/Main.java +++ b/flyway-commandline/src/main/java/org/flywaydb/commandline/Main.java @@ -244,6 +244,7 @@ private static void printUsage() { LOG.info("target : Target version up to which Flyway should use migrations"); LOG.info("outOfOrder : Allows migrations to be run \"out of order\""); LOG.info("callbacks : Comma-separated list of FlywayCallback classes"); + LOG.info("skipDefaultCallbacks : Skips default callbacks (sql)"); LOG.info("validateOnMigrate : Validate when running migrate"); LOG.info("cleanOnValidationError : Automatically clean on a validation error"); LOG.info("cleanDisabled : Whether to disable clean"); diff --git a/flyway-core/src/main/java/org/flywaydb/core/Flyway.java b/flyway-core/src/main/java/org/flywaydb/core/Flyway.java index cd7ddeee05..b941daea38 100644 --- a/flyway-core/src/main/java/org/flywaydb/core/Flyway.java +++ b/flyway-core/src/main/java/org/flywaydb/core/Flyway.java @@ -16,7 +16,9 @@ package org.flywaydb.core; -import org.flywaydb.core.api.*; +import org.flywaydb.core.api.FlywayException; +import org.flywaydb.core.api.MigrationInfoService; +import org.flywaydb.core.api.MigrationVersion; import org.flywaydb.core.api.callback.FlywayCallback; import org.flywaydb.core.api.configuration.FlywayConfiguration; import org.flywaydb.core.api.resolver.MigrationResolver; @@ -52,11 +54,14 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; /** * This is the centre point of Flyway, and for most users, the only class they will ever have to deal with. @@ -234,11 +239,17 @@ public class Flyway implements FlywayConfiguration { private boolean outOfOrder; /** - * This is a list of callbacks that fire before and after tasks are executed. You can - * add as many custom callbacks as you want. + * This is a list of custom callbacks that fire before and after tasks are executed. You can + * add as many custom callbacks as you want. (default: none) */ private FlywayCallback[] callbacks = new FlywayCallback[0]; + /** + * Whether Flyway should skip the default callbacks. If true, only custom callbacks are used. + *

(default: false)

+ */ + private boolean skipDefaultCallbacks; + /** * The custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply. *

(default: none)

@@ -784,6 +795,11 @@ public FlywayCallback[] getCallbacks() { return callbacks; } + @Override + public boolean isSkipDefaultCallbacks() { + return skipDefaultCallbacks; + } + /** * Set the callbacks for lifecycle notifications. * @@ -803,6 +819,15 @@ public void setCallbacksAsClassNames(String... callbacks) { setCallbacks(callbackList.toArray(new FlywayCallback[callbacks.length])); } + /** + * Whether Flyway should skip the default callbacks. If true, only custom callbacks are used. + * + * @param skipDefaultCallbacks Whether default built-in callbacks should be skipped.

(default: false)

+ */ + public void setSkipDefaultCallbacks(boolean skipDefaultCallbacks) { + this.skipDefaultCallbacks = skipDefaultCallbacks; + } + /** * Sets custom MigrationResolvers to be used in addition to the built-in ones for resolving Migrations to apply. * @@ -841,11 +866,12 @@ public void setSkipDefaultResolvers(boolean skipDefaultResolvers) { */ public int migrate() throws FlywayException { return execute(new Command() { - public Integer execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas) { + public Integer execute(Connection connectionMetaDataTable, Connection connectionUserObjects, + MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas, FlywayCallback[] flywayCallbacks) { MetaDataTable metaDataTable = new MetaDataTableImpl(dbSupport, schemas[0].getTable(table)); if (validateOnMigrate) { - doValidate(connectionMetaDataTable, dbSupport, migrationResolver, metaDataTable, schemas, true); + doValidate(connectionMetaDataTable, dbSupport, migrationResolver, metaDataTable, schemas, flywayCallbacks, true); } new DbSchemas(connectionMetaDataTable, schemas, metaDataTable).create(); @@ -860,7 +886,7 @@ public Integer execute(Connection connectionMetaDataTable, Connection connection if (baselineOnMigrate || nonEmptySchemas.isEmpty()) { if (baselineOnMigrate && !nonEmptySchemas.isEmpty()) { - new DbBaseline(connectionMetaDataTable, dbSupport, metaDataTable, schemas[0], baselineVersion, baselineDescription, callbacks).baseline(); + new DbBaseline(connectionMetaDataTable, dbSupport, metaDataTable, schemas[0], baselineVersion, baselineDescription, flywayCallbacks).baseline(); } } else { if (nonEmptySchemas.size() == 1) { @@ -882,7 +908,7 @@ public Integer execute(Connection connectionMetaDataTable, Connection connection DbMigrate dbMigrate = new DbMigrate(connectionMetaDataTable, connectionUserObjects, dbSupport, metaDataTable, - schemas[0], migrationResolver, target, ignoreFailedFutureMigration, outOfOrder, callbacks); + schemas[0], migrationResolver, target, ignoreFailedFutureMigration, outOfOrder, flywayCallbacks); return dbMigrate.migrate(); } }); @@ -896,10 +922,11 @@ public Integer execute(Connection connectionMetaDataTable, Connection connection */ public void validate() throws FlywayException { execute(new Command() { - public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas) { + public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, + MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas, FlywayCallback[] flywayCallbacks) { MetaDataTable metaDataTable = new MetaDataTableImpl(dbSupport, schemas[0].getTable(table)); - doValidate(connectionMetaDataTable, dbSupport, migrationResolver, metaDataTable, schemas, false); + doValidate(connectionMetaDataTable, dbSupport, migrationResolver, metaDataTable, schemas, flywayCallbacks, false); return null; } }); @@ -916,14 +943,14 @@ public Void execute(Connection connectionMetaDataTable, Connection connectionUse * @param pendingOrFuture Whether pending or future migrations are ok. */ private void doValidate(Connection connectionMetaDataTable, DbSupport dbSupport, MigrationResolver migrationResolver, - MetaDataTable metaDataTable, Schema[] schemas, boolean pendingOrFuture) { + MetaDataTable metaDataTable, Schema[] schemas, FlywayCallback[] flywayCallbacks, boolean pendingOrFuture) { String validationError = new DbValidate(connectionMetaDataTable, dbSupport, metaDataTable, schemas[0], migrationResolver, - target, outOfOrder, pendingOrFuture, callbacks).validate(); + target, outOfOrder, pendingOrFuture, flywayCallbacks).validate(); if (validationError != null) { if (cleanOnValidationError) { - new DbClean(connectionMetaDataTable, dbSupport, metaDataTable, schemas, callbacks, cleanDisabled).clean(); + new DbClean(connectionMetaDataTable, dbSupport, metaDataTable, schemas, flywayCallbacks, cleanDisabled).clean(); } else { throw new FlywayException("Validate failed. " + validationError); } @@ -939,10 +966,12 @@ private void doValidate(Connection connectionMetaDataTable, DbSupport dbSupport, */ public void clean() { execute(new Command() { - public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas) { + public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, + MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas, + FlywayCallback[] flywayCallbacks) { MetaDataTableImpl metaDataTable = new MetaDataTableImpl(dbSupport, schemas[0].getTable(table)); - new DbClean(connectionMetaDataTable, dbSupport, metaDataTable, schemas, callbacks, cleanDisabled).clean(); + new DbClean(connectionMetaDataTable, dbSupport, metaDataTable, schemas, flywayCallbacks, cleanDisabled).clean(); return null; } }); @@ -959,9 +988,9 @@ public Void execute(Connection connectionMetaDataTable, Connection connectionUse public MigrationInfoService info() { return execute(new Command() { public MigrationInfoService execute(final Connection connectionMetaDataTable, Connection connectionUserObjects, - MigrationResolver migrationResolver, final DbSupport dbSupport, final Schema[] schemas) { + MigrationResolver migrationResolver, final DbSupport dbSupport, final Schema[] schemas, FlywayCallback[] flywayCallbacks) { try { - for (final FlywayCallback callback : getCallbacks()) { + for (final FlywayCallback callback : flywayCallbacks) { new TransactionTemplate(connectionMetaDataTable).execute(new TransactionCallback() { @Override public Object doInTransaction() throws SQLException { @@ -979,7 +1008,7 @@ public Object doInTransaction() throws SQLException { new MigrationInfoServiceImpl(migrationResolver, metaDataTable, target, outOfOrder, true); migrationInfoService.refresh(); - for (final FlywayCallback callback : getCallbacks()) { + for (final FlywayCallback callback : flywayCallbacks) { new TransactionTemplate(connectionMetaDataTable).execute(new TransactionCallback() { @Override public Object doInTransaction() throws SQLException { @@ -1007,10 +1036,10 @@ public Object doInTransaction() throws SQLException { */ public void baseline() throws FlywayException { execute(new Command() { - public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas) { + public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas, FlywayCallback[] flywayCallbacks) { MetaDataTable metaDataTable = new MetaDataTableImpl(dbSupport, schemas[0].getTable(table)); new DbSchemas(connectionMetaDataTable, schemas, metaDataTable).create(); - new DbBaseline(connectionMetaDataTable, dbSupport, metaDataTable, schemas[0], baselineVersion, baselineDescription, callbacks).baseline(); + new DbBaseline(connectionMetaDataTable, dbSupport, metaDataTable, schemas[0], baselineVersion, baselineDescription, flywayCallbacks).baseline(); return null; } }); @@ -1028,9 +1057,9 @@ public Void execute(Connection connectionMetaDataTable, Connection connectionUse */ public void repair() throws FlywayException { execute(new Command() { - public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas) { + public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas, FlywayCallback[] flywayCallbacks) { MetaDataTable metaDataTable = new MetaDataTableImpl(dbSupport, schemas[0].getTable(table)); - new DbRepair(dbSupport, connectionMetaDataTable, schemas[0], migrationResolver, metaDataTable, callbacks).repair(); + new DbRepair(dbSupport, connectionMetaDataTable, schemas[0], migrationResolver, metaDataTable, flywayCallbacks).repair(); return null; } }); @@ -1171,14 +1200,18 @@ public void configure(Properties properties) { if (StringUtils.hasLength(resolversProp)) { setResolversAsClassNames(StringUtils.tokenizeToStringArray(resolversProp, ",")); } - String skipDefaultResolverProp = getValueAndRemoveEntry(props, "flyway.skipDefaultResolvers"); - if (skipDefaultResolverProp != null) { - setSkipDefaultResolvers(Boolean.parseBoolean(skipDefaultResolverProp)); + String skipDefaultResolversProp = getValueAndRemoveEntry(props, "flyway.skipDefaultResolvers"); + if (skipDefaultResolversProp != null) { + setSkipDefaultResolvers(Boolean.parseBoolean(skipDefaultResolversProp)); } String callbacksProp = getValueAndRemoveEntry(props, "flyway.callbacks"); if (StringUtils.hasLength(callbacksProp)) { setCallbacksAsClassNames(StringUtils.tokenizeToStringArray(callbacksProp, ",")); } + String skipDefaultCallbacksProp = getValueAndRemoveEntry(props, "flyway.skipDefaultCallbacks"); + if (skipDefaultCallbacksProp != null) { + setSkipDefaultCallbacks(Boolean.parseBoolean(skipDefaultCallbacksProp)); + } Map placeholdersFromProps = new HashMap(placeholders); Iterator> iterator = props.entrySet().iterator(); @@ -1231,8 +1264,6 @@ private String getValueAndRemoveEntry(Map map, String key) { Connection connectionMetaDataTable = null; Connection connectionUserObjects = null; - boolean callbackAutoAdded = false; - try { if (dataSource == null) { throw new FlywayException("Unable to connect to the database. Configure the url, user and password!"); @@ -1268,22 +1299,18 @@ private String getValueAndRemoveEntry(Map map, String key) { Scanner scanner = new Scanner(classLoader); MigrationResolver migrationResolver = createMigrationResolver(dbSupport, scanner); - if (callbacks.length == 0) { - setCallbacks(new SqlScriptFlywayCallback(dbSupport, scanner, locations, createPlaceholderReplacer(), + Set flywayCallbacks = new HashSet(Arrays.asList(callbacks)); + if (!skipDefaultCallbacks) { + flywayCallbacks.add(new SqlScriptFlywayCallback(dbSupport, scanner, locations, createPlaceholderReplacer(), encoding, sqlMigrationSuffix)); - callbackAutoAdded = true; } - for (FlywayCallback callback : callbacks) { + for (FlywayCallback callback : flywayCallbacks) { ConfigurationInjectionUtils.injectFlywayConfiguration(callback, this); } - result = command.execute(connectionMetaDataTable, connectionUserObjects, migrationResolver, dbSupport, schemas); + result = command.execute(connectionMetaDataTable, connectionUserObjects, migrationResolver, dbSupport, schemas, flywayCallbacks.toArray(new FlywayCallback[flywayCallbacks.size()])); } finally { - if (callbackAutoAdded) { - setCallbacksAsClassNames(); - } - JdbcUtils.closeConnection(connectionUserObjects); JdbcUtils.closeConnection(connectionMetaDataTable); @@ -1308,7 +1335,8 @@ private String getValueAndRemoveEntry(Map map, String key) { * @param migrationResolver The migration resolver to use. * @param dbSupport The database-specific support for these connections. * @param schemas The schemas managed by Flyway. @return The result of the operation. + * @param flywayCallbacks The callbacks to use. */ - T execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas); + T execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas, FlywayCallback[] flywayCallbacks); } } diff --git a/flyway-core/src/main/java/org/flywaydb/core/api/configuration/FlywayConfiguration.java b/flyway-core/src/main/java/org/flywaydb/core/api/configuration/FlywayConfiguration.java index 3f96a90719..2957353c29 100644 --- a/flyway-core/src/main/java/org/flywaydb/core/api/configuration/FlywayConfiguration.java +++ b/flyway-core/src/main/java/org/flywaydb/core/api/configuration/FlywayConfiguration.java @@ -27,13 +27,6 @@ */ public interface FlywayConfiguration { - /** - * Gets the callbacks for lifecycle notifications. - * - * @return The callbacks for lifecycle notifications. An empty array if none. (default: none) - */ - FlywayCallback[] getCallbacks(); - /** * Retrieves the ClassLoader to use for resolving migrations on the classpath. * @@ -42,13 +35,6 @@ public interface FlywayConfiguration { */ ClassLoader getClassLoader(); - /** - * Whether Flyway should skip the default resolvers. If true, only custom resolvers are used. - * - * @return Whether default built-in resolvers should be skipped. (default: false) - */ - boolean isSkipDefaultResolvers(); - /** * Retrieves the dataSource to use to access the database. Must have the necessary privileges to execute ddl. * @@ -78,6 +64,27 @@ public interface FlywayConfiguration { */ MigrationResolver[] getResolvers(); + /** + * Whether Flyway should skip the default resolvers. If true, only custom resolvers are used. + * + * @return Whether default built-in resolvers should be skipped. (default: false) + */ + boolean isSkipDefaultResolvers(); + + /** + * Gets the callbacks for lifecycle notifications. + * + * @return The callbacks for lifecycle notifications. An empty array if none. (default: none) + */ + FlywayCallback[] getCallbacks(); + + /** + * Whether Flyway should skip the default callbacks. If true, only custom callbacks are used. + * + * @return Whether default built-in callbacks should be skipped. (default: false) + */ + boolean isSkipDefaultCallbacks(); + /** * Retrieves the file name suffix for sql migrations. *

diff --git a/flyway-core/src/main/java/org/flywaydb/core/internal/info/MigrationInfoImpl.java b/flyway-core/src/main/java/org/flywaydb/core/internal/info/MigrationInfoImpl.java index b5955b39db..26d394c859 100644 --- a/flyway-core/src/main/java/org/flywaydb/core/internal/info/MigrationInfoImpl.java +++ b/flyway-core/src/main/java/org/flywaydb/core/internal/info/MigrationInfoImpl.java @@ -209,24 +209,24 @@ public Integer getExecutionTime() { * @return The error message, or {@code null} if everything is fine. */ public String validate() { - if (!context.pendingOrFuture - && (resolvedMigration == null) - && (appliedMigration.getType() != MigrationType.SCHEMA) - && (appliedMigration.getType() != MigrationType.BASELINE) - && (appliedMigration.getVersion() != null)) { - return "Detected applied migration not resolved locally: " + getVersion(); - } + if (!context.pendingOrFuture) { + if ((resolvedMigration == null) + && (appliedMigration.getType() != MigrationType.SCHEMA) + && (appliedMigration.getType() != MigrationType.BASELINE) + && (appliedMigration.getVersion() != null)) { + return "Detected applied migration not resolved locally: " + getVersion(); + } - if ((!context.pendingOrFuture && (MigrationState.PENDING == getState())) - || (MigrationState.IGNORED == getState())) { - if (getVersion() != null) { - return "Detected resolved migration not applied to database: " + getVersion(); + if (MigrationState.PENDING == getState() || MigrationState.IGNORED == getState()) { + if (getVersion() != null) { + return "Detected resolved migration not applied to database: " + getVersion(); + } + return "Detected resolved repeatable migration not applied to database: " + getDescription(); } - return "Detected resolved repeatable migration not applied to database: " + getDescription(); - } - if (!context.pendingOrFuture && (MigrationState.OUTDATED == getState())) { - return "Detected outdated resolved repeatable migration that should be re-applied to database: " + getDescription(); + if (MigrationState.OUTDATED == getState()) { + return "Detected outdated resolved repeatable migration that should be re-applied to database: " + getDescription(); + } } if (resolvedMigration != null && appliedMigration != null) { diff --git a/flyway-core/src/main/java/org/flywaydb/core/internal/util/jdbc/DriverDataSource.java b/flyway-core/src/main/java/org/flywaydb/core/internal/util/jdbc/DriverDataSource.java index d26ac35dca..a3d3f0bca7 100644 --- a/flyway-core/src/main/java/org/flywaydb/core/internal/util/jdbc/DriverDataSource.java +++ b/flyway-core/src/main/java/org/flywaydb/core/internal/util/jdbc/DriverDataSource.java @@ -1,12 +1,12 @@ /** * Copyright 2010-2016 Boxfuse GmbH - *

+ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

+ * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/flyway-core/src/test/java/org/flywaydb/core/FlywaySmallTest.java b/flyway-core/src/test/java/org/flywaydb/core/FlywaySmallTest.java index 7e8780772e..e08f942abb 100644 --- a/flyway-core/src/test/java/org/flywaydb/core/FlywaySmallTest.java +++ b/flyway-core/src/test/java/org/flywaydb/core/FlywaySmallTest.java @@ -16,16 +16,15 @@ package org.flywaydb.core; import org.flywaydb.core.api.FlywayException; +import org.flywaydb.core.api.callback.FlywayCallback; import org.flywaydb.core.api.resolver.MigrationResolver; import org.flywaydb.core.internal.dbsupport.DbSupport; import org.flywaydb.core.internal.dbsupport.Schema; -import org.flywaydb.core.internal.resolver.MyConfigurationAwareCustomMigrationResolver; import org.flywaydb.core.internal.resolver.MyCustomMigrationResolver; import org.flywaydb.core.internal.util.jdbc.DriverDataSource; import org.junit.Test; import javax.sql.DataSource; - import java.sql.Connection; import java.util.Properties; @@ -49,7 +48,7 @@ public void configure() { assertNotNull(flyway.getDataSource()); flyway.execute(new Flyway.Command() { - public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas) { + public Void execute(Connection connectionMetaDataTable, Connection connectionUserObjects, MigrationResolver migrationResolver, DbSupport dbSupport, Schema[] schemas, FlywayCallback[] flywayCallbacks) { assertEquals("PUBLIC", flyway.getSchemas()[0]); return null; } diff --git a/flyway-core/src/test/java/org/flywaydb/core/internal/info/MigrationInfoImplSmallTest.java b/flyway-core/src/test/java/org/flywaydb/core/internal/info/MigrationInfoImplSmallTest.java index 5ff444f54c..7ec5349c32 100644 --- a/flyway-core/src/test/java/org/flywaydb/core/internal/info/MigrationInfoImplSmallTest.java +++ b/flyway-core/src/test/java/org/flywaydb/core/internal/info/MigrationInfoImplSmallTest.java @@ -47,4 +47,19 @@ public void validate() { assertTrue(message.contains("123")); assertTrue(message.contains("456")); } + + @Test + public void validateFuture() { + MigrationVersion version = MigrationVersion.fromVersion("1"); + String description = "test"; + MigrationType type = MigrationType.SQL; + + AppliedMigration appliedMigration = new AppliedMigration(1, version, description, type, null, 123, new Date(), "abc", 0, true); + + MigrationInfoImpl migrationInfo = + new MigrationInfoImpl(null, appliedMigration, new MigrationInfoContext(), false); + String message = migrationInfo.validate(); + + assertTrue(message, message.contains("not resolved")); + } } diff --git a/flyway-core/src/test/java/org/flywaydb/core/internal/resolver/FlywayConfigurationForTests.java b/flyway-core/src/test/java/org/flywaydb/core/internal/resolver/FlywayConfigurationForTests.java index b77f32506b..9fe0fd108b 100644 --- a/flyway-core/src/test/java/org/flywaydb/core/internal/resolver/FlywayConfigurationForTests.java +++ b/flyway-core/src/test/java/org/flywaydb/core/internal/resolver/FlywayConfigurationForTests.java @@ -38,6 +38,7 @@ public class FlywayConfigurationForTests implements FlywayConfiguration { private String sqlMigrationSuffix; private MyCustomMigrationResolver[] migrationResolvers = new MyCustomMigrationResolver[0]; private boolean skipDefaultResolvers; + private boolean skipDefaultCallbacks; public FlywayConfigurationForTests(ClassLoader contextClassLoader, String[] locations, String encoding, String sqlMigrationPrefix, String repeatableSqlMigrationPrefix, String sqlMigrationSeparator, String sqlMigrationSuffix, @@ -69,6 +70,15 @@ public FlywayCallback[] getCallbacks() { return null; } + @Override + public boolean isSkipDefaultCallbacks() { + return skipDefaultCallbacks; + } + + public void setSkipDefaultCallbacks(boolean skipDefaultCallbacks) { + this.skipDefaultCallbacks = skipDefaultCallbacks; + } + @Override public ClassLoader getClassLoader() { return classLoader; diff --git a/flyway-gradle-plugin/src/main/groovy/org/flywaydb/gradle/FlywayExtension.groovy b/flyway-gradle-plugin/src/main/groovy/org/flywaydb/gradle/FlywayExtension.groovy index dc8393b2e5..bf2dd70ccb 100644 --- a/flyway-gradle-plugin/src/main/groovy/org/flywaydb/gradle/FlywayExtension.groovy +++ b/flyway-gradle-plugin/src/main/groovy/org/flywaydb/gradle/FlywayExtension.groovy @@ -134,6 +134,12 @@ public class FlywayExtension { /** An array of fully qualified FlywayCallback class implementations */ String[] callbacks + /** + * If set to true, default built-in callbacks will be skipped, only custom migration callbacks will be used. + *

(default: false)

+ */ + Boolean skipDefaultCallbacks + /** Allows migrations to be run "out of order" */ Boolean outOfOrder diff --git a/flyway-gradle-plugin/src/main/groovy/org/flywaydb/gradle/task/AbstractFlywayTask.groovy b/flyway-gradle-plugin/src/main/groovy/org/flywaydb/gradle/task/AbstractFlywayTask.groovy index d2db044414..f626278b63 100644 --- a/flyway-gradle-plugin/src/main/groovy/org/flywaydb/gradle/task/AbstractFlywayTask.groovy +++ b/flyway-gradle-plugin/src/main/groovy/org/flywaydb/gradle/task/AbstractFlywayTask.groovy @@ -107,6 +107,7 @@ abstract class AbstractFlywayTask extends DefaultTask { propSetAsBoolean(flyway, 'cleanDisabled') propSetAsBoolean(flyway, 'baselineOnMigrate') propSetAsBoolean(flyway, 'skipDefaultResolvers') + propSetAsBoolean(flyway, 'skipDefaultCallbacks') def sysSchemas = System.getProperty("flyway.schemas") if (sysSchemas != null) { diff --git a/flyway-maven-plugin/src/main/java/org/flywaydb/maven/AbstractFlywayMojo.java b/flyway-maven-plugin/src/main/java/org/flywaydb/maven/AbstractFlywayMojo.java index 195a54e413..810a023ccb 100644 --- a/flyway-maven-plugin/src/main/java/org/flywaydb/maven/AbstractFlywayMojo.java +++ b/flyway-maven-plugin/src/main/java/org/flywaydb/maven/AbstractFlywayMojo.java @@ -320,6 +320,15 @@ abstract class AbstractFlywayMojo extends AbstractMojo { */ private String[] callbacks = new String[0]; + /** + * When set to true, default callbacks are skipped, i.e. only custom callbacks as defined by 'resolvers' + * are used. (default: false)

Also configurable with Maven or System Property: + * ${flyway.skipDefaultCallbacks}

+ * + * @parameter property="flyway.skipDefaultCallbacks" + */ + private boolean skipDefaultCallbacks; + /** *

* Whether to automatically call baseline when migrate is executed against a non-empty schema with no metadata table. @@ -461,6 +470,7 @@ public final void execute() throws MojoExecutionException, MojoFailureException flyway.setResolversAsClassNames(resolvers); flyway.setSkipDefaultResolvers(skipDefaultResolvers); flyway.setCallbacksAsClassNames(callbacks); + flyway.setSkipDefaultCallbacks(skipDefaultCallbacks); flyway.setEncoding(encoding); flyway.setSqlMigrationPrefix(sqlMigrationPrefix); flyway.setRepeatableSqlMigrationPrefix(repeatableSqlMigrationPrefix); diff --git a/flyway-sbt/src/main/scala/org/flywaydb/sbt/FlywayPlugin.scala b/flyway-sbt/src/main/scala/org/flywaydb/sbt/FlywayPlugin.scala index 7cfce44add..293d582d88 100644 --- a/flyway-sbt/src/main/scala/org/flywaydb/sbt/FlywayPlugin.scala +++ b/flyway-sbt/src/main/scala/org/flywaydb/sbt/FlywayPlugin.scala @@ -64,6 +64,7 @@ object FlywayPlugin extends AutoPlugin { val flywayTarget = settingKey[String]("The target version up to which Flyway should run migrations. Migrations with a higher version number will not be applied. (default: the latest version)") val flywayOutOfOrder = settingKey[Boolean]("Allows migrations to be run \"out of order\" (default: {@code false}). If you already have versions 1 and 3 applied, and now a version 2 is found, it will be applied too instead of being ignored.") val flywayCallbacks = settingKey[Seq[String]]("A list of fully qualified FlywayCallback implementation classnames that will be used for Flyway lifecycle notifications. (default: Empty)") + val flywaySkipDefaultCallbacks = settingKey[Boolean]("Whether default built-in callbacks should be skipped. (default: false)") //********************* // settings for migrate @@ -101,7 +102,8 @@ object FlywayPlugin extends AutoPlugin { } private case class ConfigBase(schemas: Seq[String], table: String, baselineVersion: String, baselineDescription: String) private case class ConfigMigrationLoading(locations: Seq[String], resolvers: Seq[String], skipDefaultResolvers: Boolean, encoding: String, - cleanOnValidationError: Boolean, cleanDisabled: Boolean, target: String, outOfOrder: Boolean, callbacks: Seq[String]) + cleanOnValidationError: Boolean, cleanDisabled: Boolean, target: String, outOfOrder: Boolean, + callbacks: Seq[String], skipDefaultCallbacks: Boolean) private case class ConfigSqlMigration(sqlMigrationPrefix: String, repeatableSqlMigrationPrefix: String, sqlMigrationSeparator: String, sqlMigrationSuffix: String) private case class ConfigMigrate(ignoreFailedFutureMigration: Boolean, placeholderReplacement: Boolean, placeholders: Map[String, String], placeholderPrefix: String, placeholderSuffix: String, baselineOnMigrate: Boolean, validateOnMigrate: Boolean) @@ -144,6 +146,7 @@ object FlywayPlugin extends AutoPlugin { flywayTarget := defaults.getTarget.getVersion, flywayOutOfOrder := defaults.isOutOfOrder, flywayCallbacks := new Array[String](0), + flywaySkipDefaultCallbacks := defaults.isSkipDefaultCallbacks, flywayIgnoreFailedFutureMigration := defaults.isIgnoreFailedFutureMigration, flywayPlaceholderReplacement := defaults.isPlaceholderReplacement, flywayPlaceholders := defaults.getPlaceholders.asScala.toMap, @@ -160,9 +163,9 @@ object FlywayPlugin extends AutoPlugin { (schemas, table, baselineVersion, baselineDescription) => ConfigBase(schemas, table, baselineVersion, baselineDescription) }, - flywayConfigMigrationLoading <<= (flywayLocations, flywayResolvers, flywaySkipDefaultResolvers, flywayEncoding, flywayCleanOnValidationError, flywayCleanDisabled, flywayTarget, flywayOutOfOrder, flywayCallbacks) map { - (locations, resolvers, skipDefaultResolvers, encoding, cleanOnValidationError, cleanDisabled, target, outOfOrder, callbacks) => - ConfigMigrationLoading(locations, resolvers, skipDefaultResolvers, encoding, cleanOnValidationError, cleanDisabled, target, outOfOrder, callbacks) + flywayConfigMigrationLoading <<= (flywayLocations, flywayResolvers, flywaySkipDefaultResolvers, flywayEncoding, flywayCleanOnValidationError, flywayCleanDisabled, flywayTarget, flywayOutOfOrder, flywayCallbacks, flywaySkipDefaultCallbacks) map { + (locations, resolvers, skipDefaultResolvers, encoding, cleanOnValidationError, cleanDisabled, target, outOfOrder, callbacks, skipDefaultCallbacks) => + ConfigMigrationLoading(locations, resolvers, skipDefaultResolvers, encoding, cleanOnValidationError, cleanDisabled, target, outOfOrder, callbacks, skipDefaultCallbacks) }, flywayConfigSqlMigration <<= (flywaySqlMigrationPrefix, flywayRepeatableSqlMigrationPrefix, flywaySqlMigrationSeparator, flywaySqlMigrationSuffix) map { (sqlMigrationPrefix, repeatableSqlMigrationPrefix, sqlMigrationSeparator, sqlMigrationSuffix) => @@ -266,6 +269,7 @@ object FlywayPlugin extends AutoPlugin { flyway.setCallbacksAsClassNames(config.callbacks: _*) flyway.setResolversAsClassNames(config.resolvers: _*) flyway.setSkipDefaultResolvers(config.skipDefaultResolvers) + flyway.setSkipDefaultCallbacks(config.skipDefaultCallbacks) flyway } def configure(config: ConfigSqlMigration): Flyway = {