logicalFilePath

The logicalFilePath attribute is used to override the file name and path when creating the unique identifier of changesets. The logicalFilePath attribute is required when moving or renaming changelogs to prevent Liquibase from redeploying the corresponding changesets as their unique identifier will have been changed by the move.

You can specify the logicalFilePath attribute in the root section of the <databaseChangeLog> in your changelog or in a specific changeset.

Uses

Liquibase uses the following pattern to create a unique identifier for a changeset: id/author/filepath.

Even if the same file is referenced by a different filepath, it is considered a different file by Liquibase because of the unique identifier definition. The logicalFilePath attribute is used to override this behavior for one of the following purposes.

You have multiple developers sharing a changelog file

If multiple developers are sharing a changelog file and their filepaths are not identical, Liquibase may attempt to repeat the execution of the changesets to the target database unless the logicalFilePath is used.

Here are some example filepaths for two developers:

  • searchPath=/Users/developer-1/
  • searchPath=/Users/developer-2

These file paths examples allow developers to always have the same changelog path.

The logicalFilePath would need to be used in this example to override the specific developers filepath so that Liquibase would not attempt to rerun the changeset files.

Code restructuring results in a new filepath for the changelog

Another example of when logicalFilePath must be used is during code restructuring. If code restructuring results in a new filepath for a changelog, the logicalFilePath attribute can be used to prevent Liquibase from attempting to rerun the previously deployed changesets.

In this example, a changelog is being moved:

  • Previous location:db/changelog/db.changelog-1.0.xml
  • New location: db/changelog-1.0/db.changelog.xml

The logicalFilePath for the changelog would need to be set to /src/main/resources/db/changelog/db.changelog-1.0.xml to prevent Liquibase from redeploying the changesets to the database.

You want to prevent changeset id conflicts between modules

The logicalFilePath can also be used as a unique identifier to prevent duplicate changeset ids between modules from causing Liquibase collisions. If there are multiple libraries in the application and each manages its own changelog files

Root changelog versus changeset level

If the logicalFilePath is set in the root element in the changelog format, the logical path is used for all changesets within the file.

You can set the logicalFilePath within specific changesets. This allows you to set different file paths for each changeset. If it is set in both places, the changeset-level path takes precedence. Setting the logicalFilePath for specific changesets can be used when an individual changeset is moved from one file to another as part of a changelog restructuring project.

Syntax

The logicalFilePath attribute be any string, although it is often set to original/legacy path names.

For a changelog:

--liquibase formatted sql logicalFilePath:com/example/old-path.xml
--changeset your.name:1
create table company (
	id int primary key,
	name varchar(50) not null,
	address1 varchar(50),
	address2 varchar(50),
	city varchar(30)
)
--rollback drop table company

For a changeset:

--changeset your.name:1 logicalFilePath:com/example/old-path.xml

For a changelog:

{
  "databaseChangeLog": [
    {
      "logicalFilePath": "../com/example/baseChangelog.xml"
    },
    {
      "changeSet": {
        "id": "1",
        "author": "your.name",
        "changes": [
          {
            "createTable": {
              "tableName": "customer",
              "columns": [
                {
                  "column": {
                    "name": "id",
                    "type": "int",
                    "autoIncrement": true,
                    "constraints": {
                      "primaryKey": true,
                      "nullable": false
                    }
                  }
                },
                {
                  "column": {
                    "name": "firstname",
                    "type": "varchar(50)"
                  }
                },
                {
                  "column": {
                    "name": "lastname",
                    "type": "varchar(50)",
                    "constraints": {
                      "nullable": false
                    }
                  }
                },
                {
                  "column": {
                    "name": "state",
                    "type": "char(2)"
                  }
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

For a changeset:

{
  "databaseChangeLog":[
    {
      "changeSet":{
        "logicalFilePath":"../com/example/baseChangelog.xml"
      }
    }
  ]
}

For a changelog:

databaseChangeLog:
    -  logicalFilePath:  ../project/Changelog/baseChangelog.yaml
    -  changeSet:
        id:  1
        author:  your.name
        changes:
        -  createTable:
            tableName:  customer
            columns:
            -  column:
                name:  id
                type:  int
                autoIncrement:  true
                constraints:
                    primaryKey:  true
                    nullable:  false
            -  column:
                name:  firstname
                type:  varchar(50)
            -  column:
                name:  lastname
                type:  varchar(50)
                constraints:
                nullable:  false
            -  column:
                name:  state
                type:  char(2)

For a changeset:

databaseChangeLog:
    -  changeset:
        logicalFilePath: ../project/Changelog/baseChangelog.yaml

For a changelog:

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
    xmlns:pro="http://www.liquibase.org/xml/ns/pro"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
        http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
        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"
	logicalFilePath="../com/example/baseChangelog.xml">

    <changeSet id="1" author="your.name">
        <createTable tableName="person">
            <column name="id" type="int">
                <constraints primaryKey="true"/>
            </column>
            <column name="name" type="varchar(50)">
                <constraints nullable="false"/>
            </column>
            <column name="address1" type="varchar(50)"/>
            <column name="address2" type="varchar(50)"/>
            <column name="city" type="varchar(30)"/>
        </createTable>
    </changeSet>

</databaseChangeLog>

For a changeset:

<changeSet id="1" author="example" logicalFilePath="com/example/old-path.xml">