在QuestDB上运行Flyway迁移脚本报错:EXISTS(CURSOR)函数未知
QuestDB + Flyway 迁移报错:EXISTS(CURSOR) 函数不存在的解决方案
问题重现
执行Flyway迁移时触发如下错误:
ERROR: unknown function name: EXISTS(CURSOR)
原因是Flyway向QuestDB发送了依赖EXISTS(CURSOR)的元数据查询,但QuestDB虽兼容PostgreSQL接口,却未实现该函数。触发报错的查询语句如下:
select-virtual EXISTS((select-virtual 1 1 from (select [relnamespace, relname, relkind] from pg_catalog.pg_class() c join (select [oid, nspname] from pg_catalog.pg_namespace() n where nspname = $1) n on n.oid = c.relnamespace where relname = $2 and relkind = 'r') c)) EXISTS from (long_sequence(1))
可行解决方案
1. 自定义Flyway数据库方言(Dialect)
Flyway通过方言生成元数据查询,可基于PostgreSQL方言扩展,替换表存在性检查逻辑:
- 创建自定义Dialect类,继承
org.flywaydb.database.postgresql.PostgreSQLDialect - 重写
getTableExistsSql方法,返回QuestDB支持的表存在性查询,例如:@Override protected String getTableExistsSql(String schema, String table) { return "SELECT 1 FROM information_schema.tables WHERE table_schema = ? AND table_name = ? AND table_type = 'BASE TABLE'"; } - 在Flyway配置中指定自定义方言类:
flyway.databaseClass=com.yourcompany.dialect.QuestDBDialect
2. 禁用Flyway默认回调,自定义迁移逻辑
通过配置跳过Flyway默认的元数据检查回调,仅保留必要的迁移步骤:
- 添加配置:
flyway.skipDefaultCallbacks=true - 编写自定义
Callback类,实现FlywayCallback接口,只处理迁移前后的必要逻辑,避免触发含EXISTS(CURSOR)的查询。
3. JDBC层SQL拦截替换
使用JDBC代理工具(如P6Spy)拦截并修改Flyway发送的SQL:
- 配置P6Spy代理JDBC连接
- 编写SQL拦截规则,将触发报错的查询替换为QuestDB兼容的等价语句,例如:
SELECT EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema = $1 AND table_name = $2 AND table_type = 'BASE TABLE')
内容的提问来源于stack exchange,提问作者Georgi Yovchev
相关产品推荐
相关产品推荐

