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: applechangelog.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=INFOupdate 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 updatePrior 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"