2
votes

I have a simple liquibase changeset (below) which I'm trying to test.

It is the second changelog to be run after app startup.

I have coded a deliberate error where I try to create column "NEW_2" twice to force a rollback of all entries in changeset: ADD_COL_2

However even though the rollback file is generated AND I see:

INFO 4/13/16 12:17 AM: liquibase: classpath:db/changelog/db.changelog-multi-set-then-rollback.xml: classpath:db/changelog/db.changelog-multi-set-then-rollback.xml::ADD_COL_2::USER1: Rolling Back Changeset:classpath:db/changelog/db.changelog-multi-set-then-rollback.xml::ADD_COL_2::USER1

INFO 4/13/16 12:17 AM: liquibase: classpath:db/changelog/db.changelog-multi-set-then-rollback.xml: classpath:db/changelog/db.changelog-multi-set-then-rollback.xml::ADD_COL_1::USER1: Rolling Back Changeset:classpath:db/changelog/db.changelog-multi-set-then-rollback.xml::ADD_COL_1::USER1

In the logs, only the NEW_4 & NEW_5 column create is rolled back.

The ADD_COL_2 changelog does NOT appear in DATABASECHANGELOG.

ADD_COL_1 changelog does apppear in DATABASECHANGELOG.

To test if the rollback worked, I execute a Native query against TABLE_1 and I can see values for NEW_1,2.. I would only expect to see NEW_1 as NEW_2 is part of the failed changeset?

If I also query INFORMATION_SCHEMA.TABLES I see NEW_1 and NEW_2.

I have tried combinations of no rollback tag, explicit rollback tags for each statement, group tags, all to no avail. I have tried to move the Tag to its own changeset.

To me what seems to be happening is that all changes up to the failed command are not rolled back.

Do I need to manually call something ? Do I need to manually execute the rollback file, am I misunderstanding how liquibase works and it isn't automatic on failure???

I'm genuinely at my wits end here, I (think) I've run about every combination possible.. I hoping I'm doing something stupid!

Any help is immeasurably appreciated !!

I am using Spring version 4.1.7, Liquibase 3.4.2 and running the test in Junit.

Changeset: problem ADD_COL_2 is not fully rolled back, NEW_2 column remains in TABLE_1

    <changeSet id="ADD_COL_1" author="USER1" failOnError="true">
    <comment>Add column NEW_1 to TABLE_1</comment>
    <tagDatabase tag="ADD_COL_1"/>
    <addColumn tableName="TABLE_1">
        <column name="NEW_1" type="varchar(10)" value="NEW_1"/>
    </addColumn>
</changeSet>

<changeSet id="ADD_COL_2" author="USER1" failOnError="true">
    <tagDatabase tag="ADD_COL_2"/>
    <comment>Add column NEW_2 to TABLE_1</comment>
    <addColumn tableName="TABLE_1">
        <column name="NEW_2" type="varchar(10)" value="NEW_2"/>
    </addColumn>

    <comment>Add column NEW_3 to TABLE_1</comment>
    <addColumn tableName="TABLE_1">
        <column name="NEW_2" type="varchar(10)" value="NEW_3"/>
    </addColumn>

    <comment>Add column NEW_4 to TABLE_1</comment>
    <addColumn tableName="TABLE_1">
        <column name="NEW_4" type="varchar(10)"/>
    </addColumn>

    <comment>Add column NEW_5 to TABLE_1</comment>
    <addColumn tableName="TABLE_1">
        <column name="NEW_5" type="varchar(10)"/>
    </addColumn>

    <rollback>
        <dropColumn tableName="TABLE_1" columnName="NEW_2"/>
        <dropColumn tableName="TABLE_1" columnName="NEW_3"/>
        <dropColumn tableName="TABLE_1" columnName="NEW_4"/>
        <dropColumn tableName="TABLE_1" columnName="NEW_5"/>
    </rollback>
</changeSet>

**************** ADDITIONAL INFO ****************

Updates are run internally in my app, no external liquibase commands are run.

My service extends SpringLiquibase and is executed automatically once the properties are set.

1

1 Answers

3
votes

Liquibase doen't run any <rollback> sections until you ask it to do it (using liquibase command). It executes each changeset in transaction and if it fails it tries to rollback this transaction using database transactions engine (that has some limitations, for example, if you add a column A in MySQL and after it fail to add column B in the same transaction, than A is not rolled back because MySql do commit after DDL statements).