使用 DDL 数据库生成代码时找不到函数 - jooq

Posted

技术标签:

【中文标题】使用 DDL 数据库生成代码时找不到函数 - jooq【英文标题】:Function not found when generating code with DDL Database - jooq 【发布时间】:2022-01-12 16:38:19 【问题描述】:

我有一个带有 mysql 数据库的 spring boot gradle 项目。以前在 jooq 版本 3.13.6 下,我的 sql 被解析没有错误。当更新到更高的 jooq 版本(3.14.X 和 3.15.X)并使用 jooq 生成/解析迁移时,我得到以下输出:

严重的 DDLDatabase 错误:您的 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'
                        
                    
                
            
        
    

【问题讨论】:

您可以尝试在 drop view 之前添加 -- [jooq ignore start] 并在之后添加 -- [jooq ignore stop] 吗? 感谢您的评论。忽略视图确实有助于避免错误。然而,我希望有一个可以从视图中处理 sql 的解决方案。毕竟这适用于以前的 jooq 版本。 完整的堆栈跟踪和代码生成配置是什么? 我更新了问题并添加了stacktrace和更新到jooq版本3.15.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 行为,其中不带引号的标识符是小写的,而不是许多其他 RDBMS 中的大写。

当前实现中有一个错误,它还引用了内置函数,而不仅仅是用户定义的对象。见:

https://github.com/jOOQ/jOOQ/issues/9931(与“系统名称”相关的一般问题) https://github.com/jOOQ/jOOQ/issues/12752(DDLDatabase具体问题)

我能想到的唯一解决方法是再次关闭该属性,并手动将所有标识符引用为小写。或者,您可以随时连接到实际数据库,而不是使用DDLDatabase,例如by using testcontainers。无论如何,这在很多方面都会比DDLDatabase 更强大

无论如何,这是一个非常常见的问题,所以,我已经为即将到来的 jOOQ 3.16 解决了这个问题。上述设置将不再引用“系统名称”,这是众所周知的内置函数标识符

【讨论】:

以上是关于使用 DDL 数据库生成代码时找不到函数 - jooq的主要内容,如果未能解决你的问题,请参考以下文章

Day24

为啥我的代码在渲染时找不到类?

ActiveRecord 将在迁移时创建数据库,但当我尝试保存某些内容或生成架构时找不到它

传递给函数时找不到c ++向量?

生成消息时找不到主题:UNKNOWN_TOPIC_OR_PARTITION

使用 Proguard 构建库时找不到 aapt_rules.txt