Liquibase Attributes runOnChange

Liquibase tries to keep the database in a consistent state, Liquibase migrator executes each ChangeSet and keeps a record of ChangeSet id in DATABASECHANGELOG table along with the MD5 checksum of the ChangeSet. in subsequent deployments, Liquibase compare the ChangeSet id if exist in DATABASECHANGELOG table, it means the ChangeSet has been executed before, then it compares the ChangeSet MD5 checksum of ChangeSet with DATABASECHANGELOG table, if checksum is different , Liquibase throws checksum error. let's see this with an example

changelog.mysql.xml

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
    <changeSet author="wesome (generated)" id="1692523877432-1" >
        <createTable catalogName="appledb" tableName="apple">
            <column name="apple_id" type="BIGINT">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="apple_name" type="VARCHAR(255)"/>
        </createTable>
    </changeSet>
    <changeSet author="wesome (generated)" id="1692523877432-2">
        <insert catalogName="appledb" tableName="apple">
            <column name="apple_id" valueNumeric="1"/>
            <column name="apple_name" value="Macintosh"/>
        </insert>
    </changeSet>
</databaseChangeLog>

liquibase.properties (update changeLogFile file format with SQL, XML, YAML, JSON as per changelog.mysql.<format>)

changeLogFile=changelog.mysql.xml
liquibase.command.url:jdbc:mysql://localhost:3306/AppleDb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
liquibase.command.username: root
liquibase.command.password: rootroot

run the update command

liquibase update

Liquibase will print the number of ChangeSet executed in the logs

now update the changelog.mysq.xml file without changing the id attribute as below

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
    <changeSet author="wesome (generated)" id="1692523877432-1" >
        <createTable catalogName="appledb" tableName="apple">
            <column name="apple_id" type="BIGINT">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="apple_name" type="VARCHAR(255)"/>
        </createTable>
    </changeSet>
    <changeSet author="wesome (generated)" id="1692523877432-2">
        <insert catalogName="appledb" tableName="apple">
            <column name="apple_id" valueNumeric="1"/>
            <!-- <column name="apple_name" value="Macintosh"/> -->
            <column name="apple_name" value="Fuji"/>
        </insert>
    </changeSet>
</databaseChangeLog>

run the update command

liquibase update

Liquibase will throw a checksum validation failed error to notify that the ChangeSet has been modified.

Unexpected error running Liquibase: Validation Failed:
     1 changesets check sum
          changelog.mysql.xml::1692523877432-2::wesome (generated) was: 8:d2236600353b2860139fca78b183edd6 but is now: 8:088f0cfa70cebaf7e03ecd5e99e12dc6

Run Liquibase update with changeset modification

Some times requirement is to run the ChangeSet with modification, a very common example is CREATE OR REPLACE in views and stored procedures. Liquibase provides an runOnChange attribute to run the change set irrespective of modification.

Append runOnChange="true" to each ChangeSet that needs to run on modification.

changelog.mysql.xml

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
    <changeSet author="wesome (generated)" id="1692523877432-1" >
        <createTable catalogName="appledb" tableName="apple">
            <column name="apple_id" type="BIGINT">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="apple_name" type="VARCHAR(255)"/>
        </createTable>
    </changeSet>
    <changeSet author="wesome (generated)" id="1692523877432-2">
        <insert catalogName="appledb" tableName="apple">
            <column name="apple_id" valueNumeric="1"/>
            <column name="apple_name" value="Macintosh"/>
        </insert>
    </changeSet>
</databaseChangeLog>

liquibase.properties (update changeLogFile file format with SQL, XML, YAML, JSON as per changelog.mysql.<format>)

changeLogFile=changelog.mysql.xml
liquibase.command.url:jdbc:mysql://localhost:3306/AppleDb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
liquibase.command.username: root
liquibase.command.password: rootroot

run the update command

liquibase update

Liquibase will print the number of ChangeSet executed in the logs

now update the changelog.mysq.xml file without changing the id attribute as below

<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
    <changeSet author="wesome (generated)" id="1692523877432-1" >
        <createTable catalogName="appledb" tableName="apple">
            <column name="apple_id" type="BIGINT">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="apple_name" type="VARCHAR(255)"/>
        </createTable>
    </changeSet>
    <changeSet author="wesome (generated)" id="1692523877432-2"  runOnChange="true">
        <insert catalogName="appledb" tableName="apple">
            <column name="apple_id" valueNumeric="1"/>
            <!-- <column name="apple_name" value="Macintosh"/> -->
            <column name="apple_name" value="Fuji"/>
        </insert>
    </changeSet>
</databaseChangeLog>

liquibase.properties (update changeLogFile file format with SQL, XML, YAML, JSON as per changelog.mysql.<format>)

changeLogFile=changelog.mysql.xml
liquibase.command.url:jdbc:mysql://localhost:3306/AppleDb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
liquibase.command.username: root
liquibase.command.password: rootroot

run the update command

liquibase update

Liquibase will throw a checksum validation failed error to notify that the ChangeSet has been modified.

UPDATE SUMMARY
Run:                          0
Previously run:               2
Filtered out:                 0
-------------------------------
Total change sets:            2

Liquibase command 'update' was executed successfully.

follow us on