#spring-boot #h2 #jooq
#spring-boot #h2 #jooq
Вопрос:
У меня есть проект spring boot gradle с базой данных mysql. Ранее в версии jooq 3.13.6 мой sql анализировался без ошибок. При обновлении до более высокой версии jooq (3.14.X и 3.15.X) и генерации / анализе миграций с помощью jooq я получаю следующий результат:
СЕРЬЕЗНАЯ ошибка базы данных DDLD: ваша строка SQL не может быть проанализирована или интерпретирована. Это может иметь множество причин, в том числе:
- Анализатор jOOQ не понимает ваш SQL
- Логика моделирования jOOQ DDL (перевод в H2) не может имитировать ваш SQL
org.h2.jdbc.JdbcSQLSyntaxErrorException: функция «coalesce» не найдена;
Ниже приведен базовый пример sql, в котором возникает ошибка. Синтаксический анализ того же представления работал с jooq 3.13.6.
DROP VIEW IF EXISTS view1;
CREATE VIEW view1 AS
SELECT COALESCE(SUM(table1.col1), 0) AS 'sum'
FROM table1;
В настоящее время я здесь потерян. Я не вижу никаких связанных изменений в журнале изменений jooq.
Любая помощь или указания для дальнейшего изучения приветствуются.
Расширенная трассировка стека:
11:10:30 SEVERE DDLDatabase Error : Your SQL string could not be parsed or interpreted. This may have a variety of reasons, including:
- The jOOQ parser doesn't understand your SQL
- The jOOQ DDL simulation logic (translating to H2) cannot simulate your SQL
If you think this is a bug or a feature worth requesting, please report it here: https://github.com/jOOQ/jOOQ/issues/new/choose
As a workaround, you can use the Settings.parseIgnoreComments syntax documented here:
https://www.jooq.org/doc/latest/manual/sql-building/dsl-context/custom-settings/settings-parser/
11:10:30 SEVERE Error while loading file: /Users/axel/projects/service/./src/main/resources/db/migration/V5__create_view1.sql
11:10:30 SEVERE Error in file: /Users/axel/projects/service/build/tmp/generateJooq/config.xml. Error : Error while exporting schema
org.jooq.exception.DataAccessException: Error while exporting schema
at org.jooq.meta.extensions.AbstractInterpretingDatabase.connection(AbstractInterpretingDatabase.java:103)
at org.jooq.meta.extensions.AbstractInterpretingDatabase.create0(AbstractInterpretingDatabase.java:77)
at org.jooq.meta.AbstractDatabase.create(AbstractDatabase.java:332)
at org.jooq.meta.AbstractDatabase.create(AbstractDatabase.java:322)
at org.jooq.meta.AbstractDatabase.setConnection(AbstractDatabase.java:312)
at org.jooq.codegen.GenerationTool.run0(GenerationTool.java:531)
at org.jooq.codegen.GenerationTool.run(GenerationTool.java:237)
at org.jooq.codegen.GenerationTool.generate(GenerationTool.java:232)
at org.jooq.codegen.GenerationTool.main(GenerationTool.java:204)
Caused by: org.jooq.exception.DataAccessException: SQL [create view "view1" as select "coalesce"("sum"("table1"."col1"), 0) "sum" from "table1"]; Function "coalesce" not found; SQL statement:
create view "view1" as select "coalesce"("sum"("table1"."col1"), 0) "sum" from "table1" [90022-200]
at org.jooq_3.15.5.H2.debug(Unknown Source)
at org.jooq.impl.Tools.translate(Tools.java:2988)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:639)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:349)
at org.jooq.meta.extensions.ddl.DDLDatabase.load(DDLDatabase.java:183)
at org.jooq.meta.extensions.ddl.DDLDatabase.lambda$export$0(DDLDatabase.java:156)
at org.jooq.FilePattern.load0(FilePattern.java:307)
at org.jooq.FilePattern.load(FilePattern.java:287)
at org.jooq.FilePattern.load(FilePattern.java:300)
at org.jooq.FilePattern.load(FilePattern.java:251)
at org.jooq.meta.extensions.ddl.DDLDatabase.export(DDLDatabase.java:156)
at org.jooq.meta.extensions.AbstractInterpretingDatabase.connection(AbstractInterpretingDatabase.java:100)
... 8 more
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Function "coalesce" not found; SQL statement:
create view "view1" as select "coalesce"("sum"("table1"."col1"), 0) "sum" from "table1" [90022-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:576)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)
at org.h2.message.DbException.get(DbException.java:205)
at org.h2.message.DbException.get(DbException.java:181)
at org.h2.command.Parser.readJavaFunction(Parser.java:3565)
at org.h2.command.Parser.readFunction(Parser.java:3770)
at org.h2.command.Parser.readTerm(Parser.java:4305)
at org.h2.command.Parser.readFactor(Parser.java:3343)
at org.h2.command.Parser.readSum(Parser.java:3330)
at org.h2.command.Parser.readConcat(Parser.java:3305)
at org.h2.command.Parser.readCondition(Parser.java:3108)
at org.h2.command.Parser.readExpression(Parser.java:3059)
at org.h2.command.Parser.readFunctionParameters(Parser.java:3778)
at org.h2.command.Parser.readFunction(Parser.java:3772)
at org.h2.command.Parser.readTerm(Parser.java:4305)
at org.h2.command.Parser.readFactor(Parser.java:3343)
at org.h2.command.Parser.readSum(Parser.java:3330)
at org.h2.command.Parser.readConcat(Parser.java:3305)
at org.h2.command.Parser.readCondition(Parser.java:3108)
at org.h2.command.Parser.readExpression(Parser.java:3059)
at org.h2.command.Parser.parseSelectExpressions(Parser.java:2931)
at org.h2.command.Parser.parseSelect(Parser.java:2952)
at org.h2.command.Parser.parseQuerySub(Parser.java:2817)
at org.h2.command.Parser.parseSelectUnion(Parser.java:2649)
at org.h2.command.Parser.parseQuery(Parser.java:2620)
at org.h2.command.Parser.parseCreateView(Parser.java:6950)
at org.h2.command.Parser.parseCreate(Parser.java:6223)
at org.h2.command.Parser.parsePrepared(Parser.java:903)
at org.h2.command.Parser.parse(Parser.java:843)
at org.h2.command.Parser.parse(Parser.java:815)
at org.h2.command.Parser.prepareCommand(Parser.java:738)
at org.h2.engine.Session.prepareLocal(Session.java:657)
at org.h2.engine.Session.prepareCommand(Session.java:595)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1235)
at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:212)
at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:201)
at org.jooq.tools.jdbc.DefaultStatement.execute(DefaultStatement.java:102)
at org.jooq.impl.SettingsEnabledPreparedStatement.execute(SettingsEnabledPreparedStatement.java:227)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:414)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:335)
... 16 more
> Task :generateJooq FAILED
Конфигурация Jooq:
jooq {
version = "3.15.5"
edition = JooqEdition.OSS
configurations {
main {
generationTool {
generator {
name = 'org.jooq.codegen.KotlinGenerator'
strategy {
name = 'org.jooq.codegen.DefaultGeneratorStrategy'
}
generate {
relations = true
deprecated = false
records = true
immutablePojos = true
fluentSetters = true
daos = false
pojosEqualsAndHashCode = true
javaTimeTypes = true
}
target {
packageName = 'de.project.service.jooq'
}
database {
name = 'org.jooq.meta.extensions.ddl.DDLDatabase'
properties {
property {
key = 'scripts'
value = 'src/main/resources/db/migration/*.sql'
}
property {
key = 'sort'
value = 'semantic'
}
property {
key = 'unqualifiedSchema'
value = 'none'
}
property {
key = 'defaultNameCase'
value = 'lower'
}
}
}
}
}
}
}
Комментарии:
1. Можете ли вы попробовать добавить — [jooq ignore start] перед отображением и — [jooq ignore stop] после?
2. Спасибо за комментарий. Игнорирование представления помогает избежать ошибки. Тем не менее, я надеялся на решение, которое может справиться с sql из представления. В конце концов, это работало с предыдущей версией jooq.
3. Какова полная конфигурация трассировки стека и генерации кода?
4. Я обновил вопрос и добавил stacktrace и конфигурацию после обновления до версии jooq 3.15.5
5. Спасибо за обновление. Для полноты картины не могли бы вы добавить материал, который вы пропустили, где многоточие (
...
) . Этоcoalesce
или"coalesce"
? Если последнее, это может быть случай github.com/jOOQ/jOOQ/issues/11342
Ответ №1:
Вероятно, у вас установлена следующая конфигурация:
<property>
<key>defaultNameCase</key>
<value>lower</value>
</property>
В jOOQ 3.15 это преобразует все идентификаторы в нижний регистр и заключает их в кавычки перед передачей инструкции SQL в H2 за кулисами для моделирования DDL, чтобы эмулировать, например, поведение PostgreSQL, где идентификаторы без кавычек имеют нижний регистр, а не верхний регистр, как во многих других СУБД.
В текущей реализации есть ошибка, которая также цитирует встроенные функции, а не только пользовательские объекты. См.:
- https://github.com/jOOQ/jOOQ/issues/9931 (общая проблема, связанная с «системными именами»)
- https://github.com/jOOQ/jOOQ/issues/12752 (
DDLDatabase
конкретная проблема)
Единственным обходным путем, который я могу придумать, было бы снова отключить это свойство и вручную указать все идентификаторы в нижнем регистре. В качестве альтернативы, вместо использования DDLDatabase
, вы всегда можете подключиться к реальной базе данных, например, с помощью testcontainers . Во всяком случае, это будет намного надежнее во многих отношениях, чем DDLDatabase
В любом случае, это довольно частая проблема, поэтому я исправил это для предстоящего jOOQ 3.16. Вышеуказанный параметр больше не будет указывать «системные имена», которые являются хорошо известными идентификаторами встроенных функций