Sometimes before actually running the ChangeLog
or ChangeSet
, it's required to check the state of the database, user permissions, table, or schema, or sometimes skip certain changes as per environment ect, If these conditions pass, then only ChangeLog
or individual ChangeSet
should execute otherwise abort the execution.
In this scenario, Liquibase
provides and Preconditions
attribute, which checks for conditions, and if all pass then only proceed. Preconditions
can be as easy as checking database type.
<preConditions>
<dbms type="oracle" />
</preConditions>
or complex as well, like running queries and asserting the result.
<preConditions>
<sqlCheck expectedResult="0">
SELECT COUNT(*) FROM apple
</sqlCheck>
</preConditions>
except sqlCheck , SQL doesn't support any preconditions
Preconditions
can be added before executing individual ChangeSet
These are also known as local Preconditions
and Preconditions
for entire ChangeLog
files are also known as Global Preconditions
.
Global Preconditions
Preconditions
can be added to a ChangeLog
which will make sure all conditions pass otherwise, they will not run the entire ChangeLog
file. On the other hand Preconditions
on the ChangeLog
hold true for all individual ChangeSet
in the ChangeLog
tag.
In the below example, Liquibase
will check if the database is Oracle, then only it will execute the ChangeSet
, or else fail the execution and abort
<?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">
<preConditions>
<dbms type="oracle" />
</preConditions>
<changeSet author="wesome" id="1692599548266-1">
<createTable catalogName="appledb" tableName="apple">
<column autoIncrement="true" name="apple_id" type="BIGINT">
<constraints nullable="false" primaryKey="true" />
</column>
<column name="apple_name" type="VARCHAR(255)" />
<column defaultValueComputed="CURRENT_TIMESTAMP" name="current_date_time" type="datetime" />
</createTable>
</changeSet>
<changeSet author="wesome" id="1692599548266-2">
<insert catalogName="appledb" tableName="apple">
<column name="apple_id" />
<column name="apple_name" value="Macintosh" />
<column name="current_date_time" valueDate="now()" />
</insert>
</changeSet>
</databaseChangeLog>
liquibase.properties (update changeLog File 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
local preconditions
Preconditions
and can be added to individual ChangeSet
as well, in which, Liquibase
will validate each ChangeSet
Preconditions
, and if pass then only run otherwise skip it. Preconditions
on individual ChangeSet
doesn't affect other changeSet.
In the Below example, the ChangeSet
with id="1692599548266-1
has Preconditions
that table doesn't exist then only create a table ChangeSet
will execute, on the other hand ChangeSet
with id="1692599548266-2
has no Preconditions
, hence it will execute irrespective of the table exist Preconditions
.
<?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" id="1692599548266-1">
<preConditions>
<not><tableExists tableName="apple" /></not>
</preConditions>
<createTable catalogName="appledb" tableName="apple">
<column autoIncrement="true" name="apple_id" type="BIGINT">
<constraints nullable="false" primaryKey="true" />
</column>
<column name="apple_name" type="VARCHAR(255)" />
<column defaultValueComputed="CURRENT_TIMESTAMP" name="current_date_time" type="datetime" />
</createTable>
</changeSet>
<changeSet author="wesome" id="1692599548266-2">
<preConditions>
<tableExists tableName="apple" />
</preConditions>
<insert catalogName="appledb" tableName="apple">
<column name="apple_id" />
<column name="apple_name" value="Macintosh" />
<column name="current_date_time" valueDate="now()" />
</insert>
</changeSet>
</databaseChangeLog>
liquibase.properties (update changeLog File file format with SQL, XML, YAML, JSON as per changelog.mysql.)
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
Liquibase allows the combination of Preconditions
for complex requirements
<preConditions>
<or>
<and>
<dbms type="oracle" />
<runningAs username="SYSTEM" />
</and>
<and>
<dbms type="mssql" />
<runningAs username="sa" />
</and>
</or>
</preConditions>