Фон
Я взглянул на исходный код ликвибазы. Оказывается, текущая реализация (в версиях 3.6.2, 3.6.3, 3.8.0) работает немного странно.
private ChangeLogParameter findParameter(String key, DatabaseChangeLog changeLog) {
ChangeLogParameter result = null;
List<ChangeLogParameter> found = new ArrayList<>();
for (ChangeLogParameter param : changeLogParameters) {
if (param.getKey().equalsIgnoreCase(key) && param.isValid()) {
found.add(param);
}
}
if (found.size() == 1) {
// this case is typically a global param, but could also be a unique non-global param in one specific
// changelog
result = found.get(0);
} else if (found.size() > 1) {
for (ChangeLogParameter changeLogParameter : found) {
if (changeLogParameter.getChangeLog().equals(changeLog)) {
result = changeLogParameter;
}
}
}
return result;
}
Вам также нужно знать, что выражения расширяются, как только набор измененийразобран. Параметры, определенные в наборах изменений, которые еще не были прочитаны, не могут рассматриваться.
Таким образом, при первом обнаружении параметра он фактически обрабатывается, как если бы он был global=true
независимо от того, имеет ли это местоили нет.
Второй глобальный параметр с таким же именем не будет записан. Однако будет записан второй локальный параметр.
Как только список параметров содержит второй ChangeLogParameter с тем же именем, они будут расширены по-разному. Теперь он ищет последнюю определенную версию этого параметра, определенного в том же файле набора изменений, но опять же не имеет значения, глобальный он или локальный.
Ответ
Итак, чтобы ответить на мой собственный вопрос. Текущая реализация liquibase не поддерживает такого рода вещи. Кроме того, он ведет себя несколько непоследовательно в отношении расширяющихся выражений.
Решение?
Я отправил отчет об ошибке с liquibase CORE-3493 и предоставил возможное решение на GitHub. Мы должны выяснить, когда и когда это будет включено.
Я сейчас использую свою собственную разветвленную версию, которая может обработать сценарий использования, описанный в моем вопросе.