ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SQLDelight 迁移输出为合法 SQL:为 PostgreSQL 服务端与 Flyway 准备的 Gradle 配置指南

SQLDelight 迁移输出为合法 SQL:为 PostgreSQL 服务端与 Flyway 准备的 Gradle 配置指南 后端ORM【免费下载链接】sqldelightSQLDelight - Generates typesafe Kotlin APIs from SQL项目地址https://gitcode.com/gh_mirrors/sq/sqldelight点击查看免费下载当你的数据库以.sqm迁移文件为 Schema 的唯一事实来源且希望 Flyway 这类外部服务直接读取迁移脚本时SQLDelight 的迁移文件会因为包含 Kotlin 类型声明而不再是合法 SQL。本文围绕 docs/jvm_postgresql/migrations.md 的核心主题完整讲解如何通过migrationOutputDirectory与migrationOutputFileFormat两个 Gradle 配置项让 SQLDelight 生成一份可供外部服务消费的合法 SQL 迁移产物并结合仓库中的任务实现源码与集成测试说明其背后的工作原理、任务命名规则与接入方式。为什么.sqm迁移文件会失去合法 SQL 身份在 SQLDelight 中Schema 有两种来源方式详见 docs/common/index_server.mdFresh Schema在.sq文件中直接写CREATE TABLE等语句一次性从空库建出目标 SchemaMigration Schema在.sqm迁移文件中按顺序书写CREATE/ALTER语句Schema 由迁移逐步叠加而成。Migration Schema 场景下迁移文件允许使用自定义 Kotlin 类型。例如在 docs/common/types_server_migrations.md 中可以看到ALTER TABLE时可以直接为列声明暴露给 Kotlin 的类型import kotlin.String; import kotlin.collection.List; ALTER TABLE my_table ADD COLUMN new_column VARCHAR(8) AS ListString;仓库测试夹具 1.sqm 也给出了同样的用法import kotlin.collections.List; CREATE TABLE person ( id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL, friends TEXT AS ListString );问题就在这里import ...;与AS ListString这类语法是 SQLDelight 的扩展标准 SQL 引擎并不认识它们。因此一旦迁移文件里出现了自定义 Kotlin 类型整个.sqm文件就不再是合法 SQL无法直接交给 PostgreSQL 服务器或 Flyway 等外部迁移工具执行。方案总览把迁移导出为合法 SQL 产物为了让其他服务典型如 Flyway能读取迁移文件SQLDelight 提供了一种输出机制额外生成一份剥离了 SQLDelight 扩展语法、只含标准 SQL 语句的迁移文件副本。这些副本会输出到你指定的目录中再通过让 Kotlin 编译任务依赖生成任务使产物进入运行时 Classpath供外部迁移工具消费。整个链路可以概括为.sqm含 Kotlin 类型非合法 SQL │ generateMainDatabaseMigrations ▼ 输出目录.sql 文件标准 SQL供 Flyway 等服务读取 │ compileKotlin dependsOn ▼ 编译产物 / ClasspathGradle 配置两个核心配置项文档给出的 Groovy 配置如下原文括号略有缺失此处补齐为完整可用的写法sqldelight { databases { Database { migrationOutputDirectory layout.buildDirectory.dir(resources/main/migrations) migrationOutputFileFormat .sql // 默认为 .sql } } }对应 Kotlin DSL 写法为sqldelight { databases { create(Database) { migrationOutputDirectory.set(layout.buildDirectory.dir(resources/main/migrations)) migrationOutputFileFormat.set(.sql) // 默认为 .sql } } }两个配置项在源码 SqlDelightDatabase.kt 中定义如下配置项类型默认值作用migrationOutputDirectoryDirectoryProperty未设置未设置时不会注册输出任务合法 SQL 迁移产物的输出目录migrationOutputFileFormatPropertyString.sql输出文件的扩展名格式需以点号开头注意migrationOutputDirectory的语义从 SqlDelightDatabase.kt 的实现看只有当该属性被显式设置isPresent时插件才会注册迁移输出任务不设置则完全不会生成相关任务。仓库测试夹具 schema-output/build.gradle 给出了真实项目中的用法其输出目录为resources/migrationssqldelight { databases { MyDatabase { packageName app.cash.sqldelight.mysql.integration dialect(app.cash.sqldelight:mysql-dialect:${app.cash.sqldelight.VersionKt.VERSION}) migrationOutputDirectory layout.buildDirectory.dir(resources/migrations) migrationOutputFileFormat .sql } } }生成任务generateMainDatabaseMigrations配置完成后插件会注册一个名为generateMainDatabaseMigrations的任务。任务名的构成规则在 SqlDelightDatabase.kt 中一目了然generate${Source 名首字母大写}${数据库名}Migrations默认 Source 名为main默认数据库名为Database组合得到generateMainDatabaseMigrations若数据库命名为MyDatabase任务名就是generateMainMyDatabaseMigrations——集成测试 DialectIntegrationTests.kt 正是通过gradle clean generateMainMyDatabaseMigrations来驱动该任务的。该任务由 GenerateMigrationOutputTask.kt 实现其行为包含几个值得注意的细节任务被标记为CacheableTask且outputDirectory声明为OutputDirectorymigrationOutputExtension声明为Input具备 Gradle 增量缓存能力执行前会清空输出目录源码中outputDirectory.listFiles()?.forEach { it.delete() }保证产物与当前迁移文件严格一致不会残留旧版本文件对每个.sqm迁移文件逐一输出文件名取迁移文件主名去掉.sqm后缀再拼接migrationOutputFileFormat指定的扩展名输出内容为纯 SQL逐条取出sqlStmtList中的语句调用rawSqlText()取原始 SQL 文本并在末尾追加分号语句之间以空行分隔。正是第 3、4 点保证了合法 SQL的语义import声明与AS Kotlin类型这类扩展语法不会被写入输出文件外部服务拿到的是一份可以被 PostgreSQL 原生解析的标准 SQL 脚本。接入compileKotlin让 Flyway 在 Classpath 上找到迁移文档给出的核心接入方式是让 Kotlin 编译任务依赖迁移输出任务compileKotlin.configure { dependsOn generateMainDatabaseMigrations }Kotlin DSL 等价写法tasks.named(compileKotlin) { dependsOn(generateMainDatabaseMigrations) }这样做的意义在于迁移产物位于build/resources/main/migrations这类目录下时其内容会随compileKotlin的执行被纳入运行时资源。对于 Flyway 这类从 Classpath 扫描迁移脚本的服务而言只要配置了对应的迁移路径就能读取到这份合法 SQL 产物无需再手工维护一份给数据库用的 SQL 副本。完整的 PostgreSQL 服务端配置示例结合 PostgreSQL 服务端场景数据库deriveSchemaFromMigrations true、使用postgresql-dialect一份完整的构建配置可参考仓库集成测试 integration-postgresql-migrations/build.gradleplugins { alias(libs.plugins.kotlin.jvm) alias(libs.plugins.sqldelight) } sqldelight { databases { MyDatabase { packageName app.cash.sqldelight.postgresql.integration dialect(app.cash.sqldelight:postgresql-dialect:${app.cash.sqldelight.VersionKt.VERSION}) deriveSchemaFromMigrations true // 将迁移输出为合法 SQL供 Flyway 等外部服务使用 migrationOutputDirectory layout.buildDirectory.dir(resources/main/migrations) migrationOutputFileFormat .sql } } }其中deriveSchemaFromMigrations true表示 Schema 由.sqm迁移文件推导而不是写在.sq里默认false详见 docs/common/gradle.mdPostgreSQL 方言依赖为app.cash.sqldelight:postgresql-dialect与该场景的入口文档 docs/jvm_postgresql/index.md 保持一致迁移文件位于src/main/sqldelight下可通过srcDirs调整文件名必须包含数字以决定执行顺序。输出结果长什么样从.sqm到.sql以 PostgreSQL 集成测试的迁移文件为例输入 V1__Product.sqmCREATE TABLE Products ( id SERIAL PRIMARY KEY, sku VARCHAR(255) NOT NULL ); COMMENT ON TABLE Products IS Store the sku rows by id; COMMENT ON COLUMN Products.sku IS The sku is not a unique identifier;以及后续迁移 V2__Product_alter.sqmALTER TABLE Products ADD COLUMN requires_dpi BOOLEAN DEFAULT FALSE; COMMENT ON COLUMN Products.requires_dpi IS requires_dpi is false by default;这些文件本身就是合法 SQL输出任务会按迁移顺序逐条重写为带分号的语句并写入输出目录。而如果某个迁移使用了自定义 Kotlin 类型例如ALTER TABLE dog ADD COLUMN is_good INTEGER AS kotlin.Boolean DEFAULT TRUE NOT NULL;见 2.sqm输出时AS kotlin.Boolean与文件头部的import会被剥离最终产物只保留ALTER TABLE dog ADD COLUMN is_good INTEGER DEFAULT TRUE NOT NULL;这类标准 SQL。与迁移校验任务的配合需要说明的是迁移输出任务与迁移校验VerifyMigrationTask是两个独立的机制校验verifyMainDatabaseMigration任务聚合任务verifySqlDelightMigration的组成部分会在check阶段运行负责验证迁移链与 Schema 的一致性。从 VerifyMigrationTask.kt 的实现可以看到它会检查迁移文件版本是否连续发现缺口时报错Gap in migrations detected. Expected migration $expected, got $actual.并要求迁移文件名中必须包含数字输出generateMainDatabaseMigrations只负责把.sqm翻译成合法 SQL 产物两者关注点不同可以独立配置、独立使用。在服务端多团队协作场景中推荐的组合是开发侧开启verifyMigrations/verifyDefinitions保证迁移链正确同时配置migrationOutputDirectory将最终合法 SQL 提供给 DBA 或 Flyway 流水线消费。使用注意与边界输出目录每次生成前会被清空这是 GenerateMigrationOutputTask.kt 的既定行为请勿把其他文件放入该目录输出文件与迁移文件一一对应文件名保持迁移文件主名仅替换扩展名因此依赖特定命名的工具如 Flyway 的V1__xxx.sql约定需要在.sqm命名时就按版本号__描述的规范命名migrationOutputFileFormat需以点号开头默认.sql如使用其他格式如.txt同样需要带上前导点该功能对所有方言通用包括 SQLite、MySQL、PostgreSQL测试夹具schema-output即使用 MySQL 方言验证本文场景聚焦 docs/jvm_postgresql/migrations.md 所覆盖的 PostgreSQL 服务端用法产物只含语句文本输出不包含 SQLDelight 的类型映射与校验逻辑外部服务执行时需自行保证语句在其目标数据库上的兼容性。小结围绕.sqm迁移文件因自定义 Kotlin 类型而丧失标准 SQL 身份这一核心痛点SQLDelight 通过migrationOutputDirectorymigrationOutputFileFormat两个配置项与generateMainDatabaseMigrations任务为 PostgreSQL 等服务端迁移场景提供了一条编译期导出合法 SQL的可靠路径。配合compileKotlin.dependsOnFlyway 等外部服务无需再维护重复的 SQL 副本即可在 Classpath 上直接消费经过验证的迁移产物。如需继续深入可阅读仓库中相关的配置与源码Gradle 数据库配置总览、服务端 Schema 概念Fresh/Migration Schema、迁移中的自定义类型与乐观锁、GenerateMigrationOutputTask 实现 以及 迁移校验任务实现。赞分享后端ORM【免费下载链接】sqldelightSQLDelight - Generates typesafe Kotlin APIs from SQL项目地址https://gitcode.com/gh_mirrors/sq/sqldelight点击查看免费下载相关推荐如何用 Python Selenium 配置大麦自动抢票从安装到开抢的完整指南如何用 Python Selenium 配置大麦自动抢票从安装到开抢的完整指南 开票按钮亮起的那一瞬间手动操作往往跟不上网络延迟。ticket purc后端ORMFlyway与PostgreSQL无缝数据迁移指南Flyway与PostgreSQL无缝数据迁移指南 Flyway是Redgate推出的数据库迁移工具能帮助开发者轻松管理PostgreSQL数据库架构变更。数据库开发工具YimMenu Lua 脚本开发指南memory 表——进程内存扫描、分配与动态 Hook/Call 全解析YimMenu Lua 脚本开发指南memory 表——进程内存扫描、分配与动态 Hook/Call 全解析 本文围绕 YimMenu 为 Lua 脚本开发者后端ORM上一篇Win-ACME 完整指南在 Windows 上自动化申请与续订 SSL 证书下一篇Gatsby 在 Windows 上的开发环境搭建与原生模块编译排错完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表