Each database query in ChangeLog
file is subdivided into individual ChangeSet
files. liquibase update
command runs the ChangeLog
file, by default, executes each individual ChangeSet
mentioned. Liquibase
provides a labels
attribute to control and filters the execution of ChangeSet
at run time via labels attribute in CLI
.
Difference between context and labels is context allows complex filtering logic such as @ ! or and , () at compile time in ChangeSet attribute of ChangeLog file, whereas labels provides the same filtering logic at run time in CLI.
labels syntax in changelog file is as below
<changeSet author="wesome (generated)" id="1692428530882-1" labels="create">
add labelFilter in the update command
liquibase update --labelFilter="create"
Let's consider an example, assume a new table needs to be created and a record needs to be inserted in the development
environment, but in production
, only the table is required but without the data. both the query is mentioned individually ChangeSet
with create and insert labelstFilter
respectively in a ChangeLog
file as below.
changelog.mysql.sql
-- liquibase formatted sql
-- changeset wesome:1692430545055-1 labels:create
CREATE TABLE appledb.apple (apple_id BIGINT NOT NULL, apple_name VARCHAR(255) NULL);
-- changeset wesome:1692430545055-2 labels:insert
INSERT INTO appledb.apple (apple_id, apple_name) VALUES (1, 'Macintosh');
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="1692428530882-1" labels="create">
<createTable catalogName="appledb" tableName="apple">
<column name="apple_id" type="BIGINT">
<constraints nullable="false" />
</column>
<column name="apple_name" type="VARCHAR(255)" />
</createTable>
</changeSet>
<changeSet author="wesome (generated)" id="1692428530882-2" labels="insert">
<insert catalogName="appledb" tableName="apple">
<column name="apple_id" valueNumeric="1" />
<column name="apple_name" value="Macintosh" />
</insert>
</changeSet>
</databaseChangeLog>
changelog.mysql.yaml
databaseChangeLog:
- changeSet:
id: 1692431025481-1
author: wesome (generated)
labels: create
changes:
- createTable:
catalogName: appledb
columns:
- column:
constraints:
nullable: false
name: apple_id
type: BIGINT
- column:
name: apple_name
type: VARCHAR(255)
tableName: apple
- changeSet:
id: 1692431025481-2
author: wesome (generated)
labels: insert
changes:
- insert:
catalogName: appledb
columns:
- column:
name: apple_id
valueNumeric: 1
- column:
name: apple_name
value: Macintosh
tableName: apple
changelog.mysql.json
{
"databaseChangeLog": [
{
"changeSet": {
"id": "1692430982187-1",
"author": "wesome (generated)",
"labels": "create",
"changes": [
{
"createTable": {
"catalogName": "appledb",
"columns": [
{
"column": {
"constraints": {
"nullable": false
},
"name": "apple_id",
"type": "BIGINT"
}
},
{
"column": {
"name": "apple_name",
"type": "VARCHAR(255)"
}
}
],
"tableName": "apple"
}
}
]
}
},
{
"changeSet": {
"id": "1692430982187-2",
"author": "wesome (generated)",
"labels": "insert",
"changes": [
{
"insert": {
"catalogName": "appledb",
"columns": [
{
"column": {
"name": "apple_id",
"valueNumeric": 1
}
}
],
"tableName": "apple"
}
}
]
}
}
]
}
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
loglevel=INFO
update command with create labels will only create the table
liquibase update --labelFilter="create"
update command with insert labels
will only insert into the table assuming the table exists or else will throw an error
liquibase update --labelFilter="update"
update command with both comma-separated labels will execute both the ChangeSet
liquibase update --labelFilter="create, insert"
If no labelFilter
is provided in the update command, it will run all ChangeSet
even if they have labels
attribute
liquibase update
Prior to Liquibase 4.16.0, the syntax to use labels attribute in a changelog file was labels="test" and in CLI also --labels="create", So to avoid confusion in 4.16.0+, the CLI syntax was updated to labels Filter="test", However, labels are still supported in CLI.
liquibase update --labelFilter="create" or liquibase update --labels="create" or liquibase update --label-filter="create"
labels filtering
After the release of version 3.2.0+, Liquibase
allows to specify CLI labels
with AND
, OR
, !
, and ()
in the changesets.
liquibase update --labelFilter="!development"
will execute ChangeSet
with all labels except development
liquibase update --labelFilter="v1.0 or development"
will execute the ChangeSet
if the update command labels
is mentioned as v1.0 or development
liquibase update --labelFilter="!development and !production"
will execute the ChangeSet
if, in the update command, the labels
is not development
and production
labels separated with "," is equivalent to an OR operation but has the highest precedence
labelFilter="development, production" is the same as labelFilter="development OR production"
will execute the ChangeSet
if, in the update command, the labels
is either development
or production
liquibase update --labelFilter="development, test and production" is the same as liquibase update --labelFilter="(development) OR (test and production)"
will execute the ChangeSet
if, in the update command, the labels
is either development
or test and production
Liquibase allows the combination of labels to create complex logic
liquibase update --labelFilter="v1.0 or (c1.1 and !development)"
Prior to Liquibase version 4.23, if the labelFilter is not mentioned in the CLI update command, all the ChangeSet will be executed regardless of labelsFilter mentioned in ChangeSet, but in versions 4.23+, a labelsFilter mentioned with @ will only run if the labels are mentioned in CLI
LabelFilter in include and includeAll tag
A ChangeLog
file can include another ChangeLog
file with the help of the include
command or include all the ChangeLog
files in a directory with the help of includeAll
tag,
ChangeSet
for creating the apple
table and vendor
are defined in changelog.mysql.create.xml
and ChangeSet
for insertion of data in apple
table and the vendor
is defined in changelog.mysql.insert.xml
.
changelog.mysql.create.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="1692436784799-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="1692436784799-2">
<createTable catalogName="appledb" tableName="vendor">
<column name="vendor_id" type="BIGINT">
<constraints nullable="false" primaryKey="true" />
</column>
<column name="vendor_name" type="VARCHAR(20)" />
<column name="active" type="CHAR(1)" />
<column name="apple_id" type="INT" />
</createTable>
</changeSet>
</databaseChangeLog>
changelog.mysql.insert.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="1692436784799-3">
<insert catalogName="appledb" tableName="apple">
<column name="apple_id" valueNumeric="1" />
<column name="apple_name" value="Macintosh" />
</insert>
</changeSet>
<changeSet author="wesome (generated)" id="1692436784799-4">
<insert catalogName="appledb" tableName="vendor">
<column name="vendor_id" valueNumeric="1" />
<column name="vendor_name" value="Macintosh_Vendor" />
<column name="active" value="Y" />
<column name="apple_id" valueNumeric="1" />
</insert>
</changeSet>
</databaseChangeLog>
add attribute labelsFilter="create"
and labelsFilter="insert"
into respective include commands in the parent changelog.mysql.xml
file 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">
<include labels="create" file="changelog.mysql.create.xml" />
<include labels="insert" file="changelog.mysql.insert.xml" />
</databaseChangeLog>
update command with labels="create"
will only execute the ChangeSet
of changelog.mysql.create.xml
and only create tables in the database
liquibase update --labelFilter="create"
update command with labels="insert"
will only execute the ChangeSet
of changelog.mysql.insert.xml
and only insert into the table assuming the table exists or else will throw an error
liquibase update --labelFilter="insert"
Labels names are case-insensitive strings
labels
defined in ChangeSet
, databaseChangeLog, include
or includeAll
attributes are case insensitive, for example below labels
<changeSet changelog="create" author="wesome (generated)" id="1692436784799-1">
will run in both cases
liquibase update --labels="insert" or liquibase update --labels="INSERT"