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.ConfigurationPropertiesBinding;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
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.LocalContainerEntityManagerFactoryBean;
import org.springframework.util.Assert;
@ -126,7 +129,7 @@ public class FlywayAutoConfiguration {
@Bean
@ConfigurationProperties(prefix = "flyway")
public Flyway flyway() {
Flyway flyway = new Flyway();
Flyway flyway = new SpringBootFlyway();
if (this.properties.isCreateDataSource()) {
flyway.setDataSource(this.properties.getUrl(), this.properties.getUser(),
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}.
*/

@ -17,7 +17,6 @@
package org.springframework.boot.autoconfigure.flyway;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -38,9 +37,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
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.

@ -234,10 +234,21 @@ public class FlywayAutoConfigurationTests {
.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) {
this.context.register(annotatedClasses);
this.context.refresh();
}
@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
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
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
`classpath:db/migration` but you can modify that using `flyway.locations`. You can also
add a special `{vendor}` placeholder to use vendor-specific scripts. Assume the following:
[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`]
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

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

Loading…
Cancel
Save