Merge pull request #6900 from vpavic:flyway-vendor-dir

* pr/6900:
  Polish contribution
  Add support for vendor specific Flyway migration locations
pull/7763/head
Stephane Nicoll 8 years ago
commit ff28e2d380

@ -40,11 +40,14 @@ import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurat
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter; import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.MetaDataAccessException;
import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean; import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -126,7 +129,7 @@ public class FlywayAutoConfiguration {
@Bean @Bean
@ConfigurationProperties(prefix = "flyway") @ConfigurationProperties(prefix = "flyway")
public Flyway flyway() { public Flyway flyway() {
Flyway flyway = new Flyway(); Flyway flyway = new SpringBootFlyway();
if (this.properties.isCreateDataSource()) { if (this.properties.isCreateDataSource()) {
flyway.setDataSource(this.properties.getUrl(), this.properties.getUser(), flyway.setDataSource(this.properties.getUrl(), this.properties.getUser(),
this.properties.getPassword(), this.properties.getPassword(),
@ -182,6 +185,45 @@ public class FlywayAutoConfiguration {
} }
private static class SpringBootFlyway extends Flyway {
private static final String VENDOR_PLACEHOLDER = "{vendor}";
@Override
public void setLocations(String... locations) {
if (usesVendorLocation(locations)) {
try {
String url = (String) JdbcUtils.extractDatabaseMetaData(
getDataSource(), "getURL");
DatabaseDriver vendor = DatabaseDriver.fromJdbcUrl(url);
if (vendor != DatabaseDriver.UNKNOWN) {
for (int i = 0; i < locations.length; i++) {
locations[i] = locations[i].replace(
VENDOR_PLACEHOLDER,
vendor.getId());
}
}
}
catch (MetaDataAccessException ex) {
throw new IllegalStateException(ex);
}
}
super.setLocations(locations);
}
private boolean usesVendorLocation(String... locations) {
for (String location : locations) {
if (location.contains(VENDOR_PLACEHOLDER)) {
return true;
}
}
return false;
}
}
/** /**
* Convert a String or Number to a {@link MigrationVersion}. * Convert a String or Number to a {@link MigrationVersion}.
*/ */

@ -17,7 +17,6 @@
package org.springframework.boot.autoconfigure.flyway; package org.springframework.boot.autoconfigure.flyway;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -38,9 +37,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
public class FlywayProperties { public class FlywayProperties {
/** /**
* Locations of migrations scripts. * Locations of migrations scripts. Can contain the special "{vendor}" placeholder
* to use vendor-specific locations.
*/ */
private List<String> locations = new ArrayList<String>(Arrays.asList("db/migration")); private List<String> locations = new ArrayList<String>(Collections.singletonList("db/migration"));
/** /**
* Check that migration scripts location exists. * Check that migration scripts location exists.

@ -234,10 +234,21 @@ public class FlywayAutoConfigurationTests {
.isEqualTo(MigrationVersion.fromVersion("1")); .isEqualTo(MigrationVersion.fromVersion("1"));
} }
@Test
public void useVendorDirectory() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"flyway.locations=classpath:db/vendors/{vendor},classpath:db/changelog");
registerAndRefresh(EmbeddedDataSourceConfiguration.class,
FlywayAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
Flyway flyway = this.context.getBean(Flyway.class);
assertThat(flyway.getLocations()).containsExactlyInAnyOrder(
"classpath:db/vendors/h2", "classpath:db/changelog");
}
private void registerAndRefresh(Class<?>... annotatedClasses) { private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses); this.context.register(annotatedClasses);
this.context.refresh(); this.context.refresh();
} }
@Configuration @Configuration

@ -2062,9 +2062,20 @@ To automatically run Flyway database migrations on startup, add the
The migrations are scripts in the form `V<VERSION>__<NAME>.sql` (with `<VERSION>` an The migrations are scripts in the form `V<VERSION>__<NAME>.sql` (with `<VERSION>` an
underscore-separated version, e.g. '`1`' or '`2_1`'). By default they live in a folder underscore-separated version, e.g. '`1`' or '`2_1`'). By default they live in a folder
`classpath:db/migration` but you can modify that using `flyway.locations` (a list). See `classpath:db/migration` but you can modify that using `flyway.locations`. You can also
the Flyway class from flyway-core for details of available settings like schemas etc. In add a special `{vendor}` placeholder to use vendor-specific scripts. Assume the following:
addition Spring Boot provides a small set of properties in
[source,properties,indent=0]
----
flyway.locations=db/migration/{vendor}
----
Rather than using `db/migration`, this configuration will set the folder to use according
to the type of the database (i.e. `db/migration/mysql` for MySql). The list of supported
database are available in {sc-spring-boot}/jdbc/DatabaseDriver.{sc-ext}[`DatabaseDriver`].
See also the Flyway class from flyway-core for details of available settings like schemas
etc. In addition Spring Boot provides a small set of properties in
{sc-spring-boot-autoconfigure}/flyway/FlywayProperties.{sc-ext}[`FlywayProperties`] {sc-spring-boot-autoconfigure}/flyway/FlywayProperties.{sc-ext}[`FlywayProperties`]
that can be used to disable the migrations, or switch off the location checking. Spring that can be used to disable the migrations, or switch off the location checking. Spring
Boot will call `Flyway.migrate()` to perform the database migration. If you would like Boot will call `Flyway.migrate()` to perform the database migration. If you would like

@ -182,13 +182,13 @@ public enum DatabaseDriver {
private final String validationQuery; private final String validationQuery;
DatabaseDriver(String id, String name, String driverClassName) { DatabaseDriver(String id, String productName, String driverClassName) {
this(id, name, driverClassName, null); this(id, productName, driverClassName, null);
} }
DatabaseDriver(String id, String name, String driverClassName, DatabaseDriver(String id, String productName, String driverClassName,
String xaDataSourceClassName) { String xaDataSourceClassName) {
this(id, name, driverClassName, xaDataSourceClassName, null); this(id, productName, driverClassName, xaDataSourceClassName, null);
} }
DatabaseDriver(String id, String productName, String driverClassName, DatabaseDriver(String id, String productName, String driverClassName,

Loading…
Cancel
Save