SQLDelight双数据库同名表生成失败,求跨平台列ID适配方案
我在SQLDelight的Gradle配置里定义了两个数据库:
sqldelight { databases { create("Database") { packageName.set("dev.db") } create("OtherDatabase") { packageName.set("dev.db2") } } }
构建后SQLDelight报错,且未生成/build/sqldelight目录。我的需求是适配Android和iOS平台不同的ColumnId(Android用ColumnId A,iOS用ColumnId B),要生成表名、数据库文件名、包名均相同的两个文件,但现在遇到了如下报错:
Task :shared:generateCommonMainDatabaseInterface FAILED
Compiling with dialect app.cash.sqldelight.dialects.sqlite_3_18.SqliteDialect/shared/src/commonMain/sqldelight/dev/db/Tables.sq: (1, 13): Table already defined with name user
1 CREATE TABLE user(
^^^^
2 id INTEGER PRIMARY KEY,
3 name TEXT
4 )/shared/src/commonMain/sqldelight/dev/db2/Tables.sq: (1, 13): Table already defined with name user
1 CREATE TABLE user(
^^^^
2 id INTEGER PRIMARY KEY,
3 name TEXT
4 )FAILURE: Build completed with 2 failures.
1: Task failed with an exception.
What went wrong:
Execution failed for task ':shared:generateCommonMainDatabaseInterface'.
A failure occurred while executing app.cash.sqldelight.gradle.SqlDelightTask$GenerateInterfaces
Generation failed; see the generator error output for details.
2: Task failed with an exception.
What went wrong:
Execution failed for task ':shared:generateCommonMainOtherDatabaseInterface'.
A failure occurred while executing app.cash.sqldelight.gradle.SqlDelightTask$GenerateInterfaces
Generation failed; see the generator error output for details.BUILD FAILED in 3s
2 actionable tasks: 2 executed
我的表结构文件内容:
CREATE TABLE IF NOT EXISTS user( _ID INTEGER PRIMARY KEY AUTOINCREMENT, CATEGORY_ID INTEGER NOT NULL UNIQUE, );
构建环境:
- SQLDelight 2.0.2
- Gradle 8.9
- Kotlin 2.0.20
- Dialect SQLite
不需要创建两个独立的Database实例,而是利用SQLDelight的平台特定源集和隔离编译特性实现同一数据库的多平台适配,具体步骤如下:
1. 调整Gradle配置,保留单个数据库定义
删除第二个OtherDatabase,统一配置为一个数据库,确保包名一致:
sqldelight { databases { create("Database") { packageName.set("dev.db") // 统一包名 } } }
2. 按平台拆分SQL文件目录
SQLDelight支持按平台源集存放SQL文件,创建以下目录结构:
shared/ ├── src/ │ ├── commonMain/ │ │ └── sqldelight/ │ │ └── dev/db/ │ │ └── // 存放跨平台通用SQL(如无差异的查询语句) │ ├── androidMain/ │ │ └── sqldelight/ │ │ └── dev/db/ │ │ └── Tables.sq // Android专属表结构(用ColumnId A) │ └── iosMain/ │ └── sqldelight/ │ └── dev/db/ │ └── Tables.sq // iOS专属表结构(用ColumnId B)
3. 编写平台专属表结构
- Android端
Tables.sq:
CREATE TABLE IF NOT EXISTS user( _ID INTEGER PRIMARY KEY AUTOINCREMENT, -- Android用的ColumnId CATEGORY_ID INTEGER NOT NULL UNIQUE );
- iOS端
Tables.sq:
CREATE TABLE IF NOT EXISTS user( id INTEGER PRIMARY KEY AUTOINCREMENT, -- iOS用的ColumnId CATEGORY_ID INTEGER NOT NULL UNIQUE );
4. 通用查询放在commonMain目录
跨平台通用的查询语句统一放在commonMain下,比如:
-- shared/src/commonMain/sqldelight/dev/db/Queries.sq getAllUsers: SELECT * FROM user;
SQLDelight会自动按平台合并专属表结构与通用查询,生成同一包名、同一数据库类名的适配代码,分别对应Android和iOS平台。
原方案报错原因
之前创建了两个独立数据库,但它们的表名(user)在全局编译时被检测到重复,导致生成失败。而平台源集的方式是按平台隔离编译,不会出现跨平台的表名冲突问题。
内容的提问来源于stack exchange,提问作者Huy Tower

