Я настраиваю первый проект Liquibase Maven для БД MySQL. До создания триггеров все в порядке.
Я считаю, что это проблема с liquibase и JDBC, которые неправильно обрабатывают SQL с несколькими операторами, но я не могу понять, чего мне не хватает.
Вот мои зависимости pom
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-parent</artifactId>
<version>3.5.3</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.3</version>
</dependency>
Это мой включаемый файл Liquibase
<databaseChangeLog xmlns = "http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
<changeSet id = "event_horizon_1_0_0" author = "lmtyler" dbms = "mysql">
<sql>
drop trigger if exists ai_event_approval;
</sql>
</changeSet>
<changeSet id = "event_horizon_1_0_1" author = "lmtyler" dbms = "mysql">
<sqlFile splitStatements = "false" stripComments = "false" endDelimiter = "DONE" path = "01__ai_event_approval.sql" relativeToChangelogFile = "true" />
</changeSet>
</databaseChangeLog>
Это мой файл sql
CREATE DEFINER ='evclient'@'%' TRIGGER ai_event_approval
AFTER INSERT
ON event_approval
FOR EACH row
begin
insert into event_approval_log (rowAction,
actionTs,
event,
requestorEmail,
requestReason,
statusType,
approverUserId,
approverReason,
lastChangTs)
values ('I',
current_timestamp(6),
new.event,
new.requestorEmail,
new.requestReason,
new.statusType,
new.approverUserId,
new.approverReason,
new.lastChangTs);
end;
# DONE
Я ожидал, что, установив splitStatements, stripComments и endDelimiter, я заставлю liquibase отправлять весь SQL как один через JDBC.
Но я получаю эту ошибку
[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.6.3:update (default) on project event-horizon-mysql: Error setting up or running Liquibase: Migration failed for change set /Users/lmtyler/OneDrive - Walmart Inc/workspace/code/event-horizon/event-horizon-mysql/src/main/java/resources/liquibase/schema/triggers/02__au_event_approval.sql::event_horizon_1_0_1::lmtyler:
[ERROR] Reason: liquibase.exception.DatabaseException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 23 [Failed SQL: CREATE TRIGGER au_event_approval
[ERROR] AFTER UPDATE
[ERROR] ON event_approval
[ERROR] FOR EACH row
[ERROR] begin
[ERROR] insert into event_approval_log (rowAction,
[ERROR] actionTs,
[ERROR] event,
[ERROR] requestorEmail,
[ERROR] requestReason,
[ERROR] statusType,
[ERROR] approverUserId,
[ERROR] approverReason,
[ERROR] lastChangTs)
[ERROR] values ('U',
[ERROR] current_timestamp(6),
[ERROR] new.event,
[ERROR] new.requestorEmail,
[ERROR] new.requestReason,
[ERROR] new.statusType,
[ERROR] new.approverUserId,
[ERROR] new.approverReason,
[ERROR] new.lastChangTs)]
@Jens Спасибо за предложение! Изменено на updateSQL проверенный выходной файл. Они выдали правильные результаты SQL ... new.lastChangTs); end;, но когда я возвращаюсь к update, он снова усекает ; end; из SQL и получает ту же ошибку, что и выше.
Прохладный. Возможно, тогда это проблема на стороне JDBC. Вы можете попробовать использовать allowMultiQueries=true в своей конфигурации для соединения JDBC.






Ночной сон вместе с предложением @Jens Я наконец вижу проблему.
Во-первых, если вы видите мой пост, ошибка была не для SQL, как я думал.
Я думал, что это AFTER INSERT выдает ошибку, но это был AFTER UPDATE
Ключ был в том, чтобы установить splitStatements:false, установка endDelimiter не требовалась.
Вот два работающих примера:
<changeSet id = "event_horizon_1_0_1" author = "lmtyler" dbms = "mysql">
<sqlFile splitStatements = "false" stripComments = "false" path = "01__ai_event_approval.sql" relativeToChangelogFile = "true"/>
</changeSet>
с этим файлом sql
CREATE DEFINER ='evclient'@'%' TRIGGER ai_event_approval
AFTER INSERT
ON event_approval
FOR EACH row
begin
insert into event_approval_log (rowAction,
actionTs,
event,
requestorEmail,
requestReason,
statusType,
approverUserId,
approverReason,
lastChangTs)
values ('I',
current_timestamp(6),
new.event,
new.requestorEmail,
new.requestReason,
new.statusType,
new.approverUserId,
new.approverReason,
new.lastChangTs);
end;
А вот с использованием формата SQL
--changeset lmtyler:event_horizon_1_0_1 dbms:mysql splitStatements:false
CREATE TRIGGER au_event_approval
AFTER UPDATE
ON event_approval
FOR EACH row
begin
insert into event_approval_log (rowAction,
actionTs,
event,
requestorEmail,
requestReason,
statusType,
approverUserId,
approverReason,
lastChangTs)
values ('U',
current_timestamp(6),
new.event,
new.requestorEmail,
new.requestReason,
new.statusType,
new.approverUserId,
new.approverReason,
new.lastChangTs);
end;
У меня возникла та же проблема при выполнении триггера внутри тега SQL. Если вы выполняете блок кода в liquibase, не забудьте добавить splitStatements: false к тегу SQL.
<changeSet id = "your_id" author = "your_name">
<comment>your comments</comment>
<sql splitStatements = "false">
CREATE TRIGGER trigger_name
BEFORE UPDATE ON table_name FOR EACH ROW
BEGIN
--Your Code Block
END;
</sql>
</changeSet>
Может быть, это поможет, если вы позволите Liquibase работать с
updateSQLвместоupdate. Тогда liquibase не будет запускать изменения непосредственно в БД, а выведет их на стандартный ввод. Таким образом, вы можете проверить, как анализируется ваш файл sql.