Skip to content

Commit

Permalink
Fixed #1047 Using both custom and SQL callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
Axel Fontaine committed Feb 2, 2016
1 parent db84a57 commit 88c06bb
Show file tree
Hide file tree
Showing 14 changed files with 171 additions and 76 deletions.
Expand Up @@ -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.<p>(default: false)</p>
* <br>Also configurable with Ant Property: ${flyway.skipDefaultCallbacks}
*/
public void setSkipDefaultCallbacks(boolean skipDefaultCallbacks) {
flyway.setSkipDefaultCallbacks(skipDefaultCallbacks);
}

/**
* @param table <p>The name of the schema metadata table that will be used by Flyway.</p><p> By default (single-schema mode) the
* metadata table is placed in the default schema for the connection provided by the datasource. </p> <p> When the
Expand Down
5 changes: 5 additions & 0 deletions flyway-commandline/src/main/assembly/flyway.conf
Expand Up @@ -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=

Expand Up @@ -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");
Expand Down
100 changes: 64 additions & 36 deletions flyway-core/src/main/java/org/flywaydb/core/Flyway.java

Large diffs are not rendered by default.

Expand Up @@ -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.
*
Expand All @@ -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.
*
Expand Down Expand Up @@ -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.
* <p/>
Expand Down
Expand Up @@ -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) {
Expand Down
@@ -1,12 +1,12 @@
/**
* Copyright 2010-2016 Boxfuse GmbH
* <p/>
*
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
*
* 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.
Expand Down
Expand Up @@ -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;

Expand All @@ -49,7 +48,7 @@ public void configure() {
assertNotNull(flyway.getDataSource());

flyway.execute(new Flyway.Command<Void>() {
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;
}
Expand Down
Expand Up @@ -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"));
}
}
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
Expand Up @@ -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.
* <p>(default: false)</p>
*/
Boolean skipDefaultCallbacks

/** Allows migrations to be run "out of order" */
Boolean outOfOrder

Expand Down
Expand Up @@ -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) {
Expand Down
Expand Up @@ -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)<br> <p>Also configurable with Maven or System Property:
* ${flyway.skipDefaultCallbacks}</p>
*
* @parameter property="flyway.skipDefaultCallbacks"
*/
private boolean skipDefaultCallbacks;

/**
* <p>
* Whether to automatically call baseline when migrate is executed against a non-empty schema with no metadata table.
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 8 additions & 4 deletions flyway-sbt/src/main/scala/org/flywaydb/sbt/FlywayPlugin.scala
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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) =>
Expand Down Expand Up @@ -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 = {
Expand Down

0 comments on commit 88c06bb

Please sign in to comment.