The manual describes the option relativeToChangeLogFile
for the sqlFile
tag as:
Indicates whether the file path is relative to the root changelog
However Liquibase 4.3.3 takes this as “relative to the current directory”.
My setup is like this:
I have the following directory structure:
MyProject
changelog\
views\
view_1.sql
main.xml
views.xml
`views.xml` is included from `main.xml` and contains this changeSet:
<changeSet author="...." id="1" runOnChange="true">
<sqlFile path="views/view_1.sql"
encoding="UTF-8"
relativeToChangelogFile="true"
stripComments="false"
splitStatements="true" endDelimiter=";" />
</changeSet>
I run Liquibase from the parent directory of changelog
, e.g.
c:\MyProject> liquibase --changeLogFile=changelog\main.xml ....
This worked fine with Liquibase 2.x and 3.x but in Liquibase 4.3.3 it fails with the following confusing error message:
Unexpected error running Liquibase: java.io.IOException: The file views/view_1.sql was not found in
- c:\MyProject\.
- c:\MyProject\postgresql-42.2.18.jar
Specifying files by absolute path was removed in Liquibase 4.0. Please use a relative path or add '/' to the classpath parameter.
So Liquibase apparently searches the file relative to the current directory, not relative to the master change log file as stated in the manual.
The error message is also confusing as I am not using an absolute file path, but a relative one.
Is there any way to get the 3.x behaviour back? Should I report this as a bug?
I’m seriously considering going back to 3.x because of this. This breaks many projects, and we can’t afford to modify all changelogs because of that - which wouldn’t really help anyway as the “current directory” might be different depending on the environment where this is run (manually, Maven, Jenkins, etc)
Note that <include ... relativeToChangelogFile="true"/>
works as expected - so there is a difference in the processing of this attribute between <include>
and <sqlFile>
. Which makes be think this is a bug even more.
The stacktrace might be interesting as it does not even mention the SQLFileChange
class. So this seems to fail before the tag gets to see the file name:
at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:124)
at liquibase.changelog.DatabaseChangeLog.validate(DatabaseChangeLog.java:292)
at liquibase.Liquibase.lambda$update$1(Liquibase.java:237)
at liquibase.Scope.lambda$child$0(Scope.java:160)
at liquibase.Scope.child(Scope.java:169)
at liquibase.Scope.child(Scope.java:159)
at liquibase.Scope.child(Scope.java:138)
at liquibase.Liquibase.runInScope(Liquibase.java:2369)
at liquibase.Liquibase.update(Liquibase.java:217)
at liquibase.Liquibase.update(Liquibase.java:203)
at liquibase.integration.commandline.Main.doMigration(Main.java:1802)
at liquibase.integration.commandline.Main$1.lambda$run$0(Main.java:367)
at liquibase.Scope.lambda$child$0(Scope.java:160)
at liquibase.Scope.child(Scope.java:169)
at liquibase.Scope.child(Scope.java:159)
at liquibase.Scope.child(Scope.java:138)
at liquibase.integration.commandline.Main$1.run(Main.java:366)
at liquibase.integration.commandline.Main$1.run(Main.java:196)
at liquibase.Scope.child(Scope.java:169)
at liquibase.Scope.child(Scope.java:145)
at liquibase.integration.commandline.Main.run(Main.java:196)
at liquibase.integration.commandline.Main.main(Main.java:158)