You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:54:55