28

I have configured the maven pluggin for liquibase as specified in maven configuration.
Now created a changeset like :-

<changeSet id="changeRollback" author="nvoxland">
  <createTable tableName="changeRollback1">
     <column name="id" type="int"/>
  </createTable>
  <rollback>
     <dropTable tableName="changeRollback1"/>
  </rollback>
</changeSet>

Created the sql to update DB using command line :- mvn liquibase:updateSQL

But just want to know how to rollback using a "rollbackTag" parameter. i.e. If run the command "mvn liquibase:rollbackSQL", what should be the value of "rollbackTag" parameter.

And is it possible to rollback using the changeset id ?

Manu
  • 3,467
  • 3
  • 29
  • 28

3 Answers3

50

Rollback tags are designed to checkpoint your database's configuration.

The following commands will roll the database configuration back by 3 changesets and create a tag called "checkpoint":

mvn liquibase:rollback -Dliquibase.rollbackCount=3
mvn liquibase:tag -Dliquibase.tag=checkpoint

You can now update the database, and at any stage rollback to that point using the rollback tag:

mvn liquibase:rollback -Dliquibase.rollbackTag=checkpoint

or alternatively generate the rollback SQL:

mvn liquibase:rollbackSQL -Dliquibase.rollbackTag=checkpoint

Revised example

I initially found it difficult to figure out how to configure the liquibase Maven plugin. Just in case it helps here's the example I've used.

The liquibase update is configured to run automatically, followed by tagging the database at the current Maven revision number.

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.myspotontheweb.db</groupId>
    <artifactId>liquibase-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <!-- Liquibase settings -->
        <liquibase.url>jdbc:h2:target/db1/liquibaseTest;AUTO_SERVER=TRUE</liquibase.url>
        <liquibase.driver>org.h2.Driver</liquibase.driver>
        <liquibase.username>user</liquibase.username>
        <liquibase.password>pass</liquibase.password>
        <liquibase.changeLogFile>com/myspotontheweb/db/changelog/db-changelog-master.xml</liquibase.changeLogFile>
        <liquibase.promptOnNonLocalDatabase>false</liquibase.promptOnNonLocalDatabase>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.3.162</version>
        </dependency>
    </dependencies>
    <profiles>
        <profile>
            <id>dbupdate</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.liquibase</groupId>
                        <artifactId>liquibase-maven-plugin</artifactId>
                        <version>2.0.2</version>
                        <executions>
                            <execution>
                                <phase>process-resources</phase>
                                <configuration>
                                    <tag>${project.version}</tag>
                                </configuration>
                                <goals>
                                    <goal>update</goal>
                                    <goal>tag</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

Liquibase is now configured as part of the standard life-cycle so can be run as follows:

mvn clean compile
Mark O'Connor
  • 76,015
  • 10
  • 139
  • 185
  • While trying to create rollbackSQL, i got the error :- [INFO] Error setting up or running Liquibase: liquibase.exception.RollbackImpossibleException: No inverse to liquibase.change.core.UpdateDataChange created – Manu Jul 06 '12 at 12:05
  • 2
    @gfghj That's really a new question. Your problem is that you have a changset that does not have an automatic rollback option. Check the refactoring documentation webpage. http://www.liquibase.org/manual/refactoring_commands. Each action will indicate if there is an automatic rollback option. Problem is fixed by specifying your own "rollback" section within the changeset – Mark O'Connor Jul 06 '12 at 23:37
  • Hi, I tried the implementation with liquibase tagging on a maven lifecycle phase and noticed that LB inserted a separate db row in the DATABASECHANGELOG table for the tag. Is this ok or I have to further configure the maven execution in order to make it proper? The db row for tag: 1480674890164,liquibase,liquibase-internal,2016-12-02 12:34:50,1,EXECUTED,7:d41d8cd98f00b204e9800998ecf8427e,Empty,,0.0.1-SNAPSHOT,3.2.2 – jtonic Dec 02 '16 at 10:44
  • Moreover, the tag related row still remained in the table after I was performing the rollback. – jtonic Dec 02 '16 at 10:51
23

I personally prefer to put the tag as part of the changeset files, so if you have to rollback or delete all the records in the DATABASECHANGELOG you won't loose your tagging records.

<databaseChangeLog>
    <changeSet id="001_create_tables" .../>
    <changeSet id="002_alter_tables" .../>
    <changeSet id="003_load_user_data" .../>

    <!-- Also include the tagging itself as a changeSet... -->
    <changeSet author="userId" id="tag_version_0_1_0">
        <tagDatabase tag="version_0.1.0" />
    </changeSet>
    <!-- version 0.1.0 ends here -->

</databaseChangeLog>
pbaris
  • 4,525
  • 5
  • 37
  • 61
kothvandir
  • 2,111
  • 2
  • 19
  • 34
  • 3
    Thanks a lot. I have created the maven goal rollbackSQL and in the configuration added the tag version_0.1.0. But when I run the goal rollbackSQL, its not generating the rollback script. But if I specify the rollback count using 2 the rollback scripts are created for the last two changesets. Any idea why the rollback script not generated? – Manu Aug 16 '12 at 13:50
  • Did you try to launch the rollbackSQL command directly from liquibase command-line? just to be sure that the current state of your DB schema and the state referred by your tag are different and so the command must outcome some SQL. – kothvandir Aug 17 '12 at 07:43
  • No. I ran it using maven plugin. But I could see the tag got added in the generated SQL when run the updateSQL goal and I updated the DB with it. I am sure the tags are not different. – Manu Aug 18 '12 at 11:09
  • 6
    Should the tagDatabase always be self-contained in its own changeSet tag? – Wand Maker Dec 17 '13 at 08:03
0

I just wanted to mention the possibility of using yq (for YAML or JSON) or jq (for JSON only) to automatically add a tag to the latest changeset of a given changelog:

yq eval --inplace ".databaseChangeLog[-1].changeSet.changes += { \"tagDatabase\": { \"tag\": \"$version\" } }" "$changelog"

Assuming $version to be 1.0.0 and $changelog being the path to a file that contains:

databaseChangeLog:
  - changeSet:
      id: 1690058672595-1
      author: ccjmne (generated)
      changes:
        - addColumn:
            columns:
              - column:
                  name: test
                  type: varchar
            tableName: my_table

Then the yq command I shared would update the contents of your changelog to:

databaseChangeLog:
  - changeSet:
      id: 1690058672595-1
      author: ccjmne (generated)
      changes:
        - addColumn:
            columns:
              - column:
                  name: test
                  type: varchar
            tableName: my_table
        - tagDatabase:
            tag: 1.0.0

(notice the last two lines, adding the appropriate tag to this changeset)

In case multiple changesets are present in your changelog, the last one gets the tag.

ccjmne
  • 9,333
  • 3
  • 47
  • 62