Parameter Substitution in logicalFilePath

We are upgrading from 1.9.5 (I know!) to 4.6.1 and found that parameter substitution seems to no longer apply to the logicalFilePath attribute of the databaseChangeLog element.

We have multiple changelog files and depend on the logicalFilePath to normalize them regardless of their location. All changelog files have the attribute defined like this:

logicalFilePath="db.upgrade.changelog.${version}.xml"

Prior to upgrade, the file name recorded in the DATABASECHANGELOG table looked like this: db.upgrade.changelog.2020.3.2.xml

After the upgrade it is saved like this: db.upgrade.changelog.${version}.xml

Other parameters in the changelog appear to be working fine, so it seems to be specific to the databaseChangeLog element or logicalFilePath attribute.

Are there any ways to get this working or accomplish the same thing in a different way?

Hi @jmeyers How were you replacing the ${version} in the 1.9.5 version of Liquibase?
A quick workaround without knowing all the details might be to have a script replace the values before calling Liquibase update and use that new changelog file.

Thanks for the reply. In 1.9.5 it worked by setting 2 parameter values using setChangeLogParameterValue() on the Liquibase object before calling update().

In 4.6.1 the only difference is I call setChangeLogParameter() as the old method no longer exists. One of the parameter substitutions seems to work and one does not. The working one uses “parentDir” to help specify the location of an sqlFile. Here is the whole changelog file:

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9"
				   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
				   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd"
				   logicalFilePath="db.upgrade.changelog.${version}.xml">
				   
	<changeSet author='daaSystem' id='1'>
		<sqlFile path="${parentDir}db.upgrade.sql" />
	</changeSet>

</databaseChangeLog>

The only difference I am aware of between the two are: one is in the “header” (i.e. the databaseChangeLog element itself) and one is in the body. I tried different names in case “version” had special meaning, but no joy.

This change in behavior may track back to CORE-1874 when DatabaseChangeLog.load() was modified to extract the logicalFilePath before performing any expression expansion.

Can anyone with internal knowledge of this change or how things should work please comment?

Is there an alternate way to dynamically change the logicalFilePath since expressions don’t seem to apply anymore?

Sometimes I think I am talking to myself in these threads, but at least I can document the process and findings :grinning:

I believe I have successfully worked around this issue by doing the substitution myself. Setting the DatabaseChangeLog logicalFilePath was not sufficient (apparently a LOT of stuff happens in the constructor) I had to dig through each of the ChangeSet and set the filePath and storedFilePath, then it appears to work like it did years ago.

This is essentially what I had to do:

Liquibase liquibase = new Liquibase(changeLogFile, sra, db);

String lfp = liquibase.getDatabaseChangeLog().getLogicalFilePath();
lfp = lfp.replace("${version}", changeLog.getVersion());
liquibase.getDatabaseChangeLog().setLogicalFilePath(lfp);

List<ChangeSet> csList = liquibase.getDatabaseChangeLog().getChangeSets();
for (ChangeSet cs : csList) {
	cs.setStoredFilePath(lfp);
	cs.setFilePath(lfp);
}