Liquibase Attributes Labels

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"

follow us on