Using Flyway to load data conditionally on Wednesday

Does flyway support conditional script execution for each environment?

For example, if I have test data, can I create a script test data folder that will only be loaded if the env is configured as a test?

+3


source to share


4 answers


If you are using maven you can achieve this easily with the concept of maven profiles. Please refer to the following sample

pom.xml



<plugin>
    <groupId>com.googlecode.flyway</groupId>
    <artifactId>flyway-maven-plugin</artifactId>
    <version>2.3</version>
    <configuration>
        <url>jdbc:sqlserver://${db.hostname};databaseName=${db.name}</url>
        <user>${db.username}</user>
        <password>${db.password}</password>
        <initVersion>0</initVersion>
        <initDescription>Base Migration</initDescription>
        <table>Changelog_testproject</table>
        <locations>
           <location>filesystem:${sql.file.path}</location>
        </locations>
    </configuration>
</plugin>

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <profile.name>dev</profile.name>
            <sql.file.path>${basedir}/deploy/dev/sqldelta/sqlserver</sql.file.path> 
            <db.hostname>127.0.0.1:1433</db.hostname>
            <db.name>dev</db.name>
            <db.username>dev</db.username>
            <db.password>devadmin</db.password>
        </properties>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <profile.name>test</profile.name>
            <sql.file.path>${basedir}/deploy/test/sqldelta/sqlserver</sql.file.path>  
            <db.hostname>127.0.0.1:1433</db.hostname>
            <db.name>test</db.name>
            <db.username>test</db.username>
            <db.password>testadmin</db.password>
        </properties>
    </profile>
 </profiles>

      

+3


source


For future visitors, this is a SQL specific solution, but it also applies to loading data. https://flywaydb.org/documentation/faq#db-specific-sql



You can set property flyway.locations = sql / common, sql / data and this can be set to different values ​​using spring profiles (dev / test / prod), omitting sql / data scripts in production.

+3


source


Maven profiles didn't give me the flexibility I wanted. I came up with a strategy that uses ant to concatenate files. This allows me to have common scenarios and then include additional data depending on the deployment type, for example. prod, dev.

This is my project structure:

β”œβ”€β”€ build.xml
β”œβ”€β”€ database.properties
β”œβ”€β”€ database.properties.template
β”œβ”€β”€ lib
β”‚   └── ant-contrib-1.0b3.jar
β”œβ”€β”€ pom.xml
└── sql
    β”œβ”€β”€ common
    β”‚   β”œβ”€β”€ V1.0__.sql
    β”‚   β”œβ”€β”€ V1.2.1__.sql
    β”‚   └── V1.3__.sql
    β”œβ”€β”€ dev
    β”‚   β”œβ”€β”€ V1.0__.sql
    β”‚   └── V1.3__.sql
    └── prod
        └── V1.0__.sql

      

the database.properties.template file in the root folder, before starting it you need to manually copy it to database.properties and enter your username and password. database.properties should be ignored by VCS to prevent passwords from ending up in the repo.

the deployType scripts are merged into a directory src/main/resources/db/migrate

, this is what the ant script stands for, please note that the scripts to be merged have the same name:

<project name="data" default="prepareSql">

    <property file="database.properties" />
    <property name="destDir" value="src/main/resources/db/migration" />

    <echo message="Deploy type: ${deployType}"/>

    <taskdef resource="net/sf/antcontrib/antcontrib.properties">
      <classpath>
        <pathelement location="lib/ant-contrib-1.0b3.jar"/>
      </classpath>
    </taskdef>

    <target name="prepareSql">
        <!-- ensure the dest dir exists -->
        <mkdir dir="${destDir}"/>

        <!-- clear out the dest dir -->
        <delete>
            <fileset dir="${destDir}">
                <include name="*" />
            </fileset>
        </delete>

        <!-- append the deploy type files to the common files, delegate to the append target -->
        <foreach target="append" param="file">
            <fileset dir="sql/common" casesensitive="yes">
                <include name="*" />
            </fileset>
        </foreach>
    </target>

    <target name="append">
        <basename property="basename" file="${file}" />
        <property name="destFile" value="${destDir}/${basename}"/>
        <echo message="Appending ${file} to ${destFile}" />

        <concat destfile="${destFile}" >
            <filelist dir="sql/common" files="${basename}" />
            <filelist dir="sql/${deployType}" files="${basename}" />
        </concat>
    </target>
</project>

      

This ant file is executed by maven, here is the pom config:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>data</groupId>
    <artifactId>data</artifactId>
    <version>1.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>data</name>

    <properties>
        <sqlBaseDir>filesystem:${basedir}/src/main/resources/</sqlBaseDir>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <id>mergeScripts</id>
                        <phase>validate</phase>
                        <inherited>false</inherited>
                        <configuration>
                            <target>
                                <ant antfile="build.xml" target="prepareSql" />
                            </target>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.flywaydb</groupId>
                <artifactId>flyway-maven-plugin</artifactId>
                <version>3.2.1</version>
                <configuration>
                    <schemas>
                        <schema>common</schema>
                    </schemas>
                    <configFile>database.properties</configFile>
                    <table>flyway</table>
                    <locations>
                        <location>filesystem:${basedir}/src/main/resources/db/migration</location>
                    </locations>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.36</version>
        </dependency>
    </dependencies>
</project>

      

If you need different data for different client distributions, you can add dist directories to sql directory and they can contain deployType sub directories.

Add a dist property to your database.properties.template file and then modify the added target in your build.xml file to look like this:

<target name="append">
    <basename property="basename" file="${file}" />
    <property name="destFile" value="${destDir}/${basename}"/>
    <echo message="Appending ${file} to ${destFile}" />

    <concat destfile="${destFile}" >
        <filelist dir="sql/common" files="${basename}" />
        <filelist dir="sql/${deployType}" files="${basename}" />
            <filelist dir="sql/${dist}/common" files="${basename}" />
            <filelist dir="sql/${dist}/${deployType}" files="${basename}" />
    </concat>
</target>

      

+1


source


You can use placeway placeholder :

Configure it in your environment settings config.properties:

flyway.placeholders. TABLENAME = my_table

flyway.placeholders. Name = 'Mr. Test '

Then put it in a script: INSERT INTO $ {tableName} (name) VALUES ( $ {name} );

I've also used flyway.locations, but placeholders are simpler than locations for simple changes.

0


source







All Articles