且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Liquibase-生成脚本而不将变更集应用于数据库

更新时间:2023-02-07 12:56:59

UpdateSQL实际上并不更新数据库,它只是输出SQL.

之所以需要数据库连接信息并进行实际连接是因为它需要从databasechangelog表中进行选择,以确定已运行和未运行哪些changeSet.

In my current project, there's a DB team that checks all the scripts before applying them to production.

We are using Liquibase to apply changesets to development, but for production, we need to be able to generate a *.sql file with all the statements.

According to the documentation of liquibase-maven-plugin, updateSQL should be what I want: http://www.liquibase.org/documentation/maven/maven_updatesql.html.

So I created two maven profiles. One to apply changes to the local development database (using liquibase:update) and one other that would just generate the script. The problem is: doing liquibase:updateSQL does generate the *.sql file (as expected), but it also tries to connect to the database and apply changes (not expected). I believe the documentation for updateSQL leads into error as it says:

Generates the SQL that is required to update the database to the current version as specified in the DatabaseChangeLogs.

Makes no mention whatsoever that it would actually apply the changesets, like liquibase:update does.

I may be missunderstanding the documentation here, but shouldn't updateSQL only generate the sql or it should actually do update + generate sql?

Here's my plugin configuration:

<plugin>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-maven-plugin</artifactId>
    <version>3.0.5</version>
    <configuration>
        <changeLogFile>src/main/resources/db/liquibase_changeset.xml</changeLogFile>
        <driver>oracle.jdbc.driver.OracleDriver</driver>
        <url>${liquibase.db.url}</url>
        <username>${liquibase.db.user}</username>
        <password>${liquibase.db.password}</password>
        <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
    </configuration>
    <executions>
        <execution>
            <phase>process-resources</phase>
            <goals>
                <goal>${liquibase.exec.goal}</goal>
            </goals>
        </execution>
    </executions>
</plugin>

And I created the profiles likes this:

<profiles>
    <profile>
        <id>local</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <liquibase.exec.goal>update</liquibase.exec.goal>
            <liquibase.exec.prompt>false</liquibase.exec.prompt>
            <liquibase.db.url>jdbc:oracle:thin:@host:1521:xe</liquibase.db.url>
            <liquibase.db.user>user</liquibase.db.user>
            <liquibase.db.password>password</liquibase.db.password>
        </properties>
    </profile>

    <profile>
        <id>uat</id>
        <properties>
            <liquibase.exec.goal>updateSQL</liquibase.exec.goal>
            <liquibase.exec.prompt>true</liquibase.exec.prompt>
            <liquibase.db.url>jdbc:oracle:thin:@host2:1521:xe</liquibase.db.url>
            <liquibase.db.user>user2</liquibase.db.user>
            <liquibase.db.password>password2</liquibase.db.password>
        </properties>
    </profile>
</profiles>

Given my maven config and my understanding, I would expect

mvn install -P uat

to only generate the script and not trying to connect to the database.

The fact that I'm forced to specify db properties (driver, etc) makes me believe that this is intended to always change database, but I suppose it should be possible to just generate the script without attempting to apply changes against a database.

Any thoughts? Is it possible but I'm completely in the wrong path? Or I'm missing some simple property? Or it's simply not supported at all?

Thanks in advance.

UpdateSQL does not actually update the database, it just outputs SQL.

The reason it needs the database connection information and makes an actual connection because it needs to select from the databasechangelog table to determine which changeSets have been ran and which have not.