言舟:SQLite 驱动
使用 ABI v2 原生 SQLite、安全参数、预编译资源、事务、反射、迁移与 JSON1 言据路径。
言库·轻舟(包名 言舟,仓库 yanxu-sqlite)是建立在言库 1.x 协议上的 SQLite 驱动。1.0 的默认后端通过 ABI v2 原生扩展在进程内使用固定版本 SQLite;系统 sqlite3 CLI 只作为显式兼容后端保留。
| 项目 | 1.0 稳定边界 |
|---|---|
| 当前版本 | 1.0.0 |
| 最低言序 | 1.1.12 |
| 稳定依赖 | 言库 v1.0.0 / ^1.0 |
| 默认 SQLite | bundled SQLite 3.53.2 |
| CLI 兼容后端 | 系统 SQLite 3.38+ |
| 原生 ABI | v2 |
| 运行方式 | 字节码 VM、包运行或 YXB;树解释器不能载入 |
安装并固定公开标签
yanbao add sqlite --package 言舟 --version "^1.0"等价的可复现清单:
[依赖]
言舟 = { git = "https://github.com/yanxulang/yanxu-sqlite.git", 修订 = "v1.0.0", 版 = "^1.0" }
[权限]
文件 = ["data"]
原生扩展 = true文件权限应只覆盖真实数据库目录;SQLite 还会在同目录创建或访问 WAL/SHM 伴随文件。纯内存数据库可保持文件权限为空。使用 CLI 兼容后端时还要授权 进程 = true。
打开数据库
引「包:言舟」为 言舟;
定 数据库 为 言舟.打开配置({
「路径」:「data/应用.db」,
「日志模式」:「WAL」,
「同步模式」:「NORMAL」,
「外键」:真,
「忙碌超时毫秒」:5000
});
数据库.执行(
「CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT NOT NULL)」,
【】
);
定 插入 为 数据库.预编译(「INSERT INTO users(name) VALUES (?)」);
插入.执行(【「子衿」】);
插入.关闭();
定 用户 为 数据库.查询(
「SELECT id, name FROM users WHERE name = ?」,
【「子衿」】
).首行();
言 用户;
数据库.关闭();便捷入口包括:
打开(路径):可创建的原生文件数据库;打开内存():独立:memory:数据库;打开临时():SQLite 管理生命周期的临时数据库;打开URI(URI):显式 SQLitefile:URI;打开只读(路径)/打开只读URI(URI):只读打开;打开CLI(路径)/打开为(路径, 程序, 超时毫秒):显式 CLI 后端;以执行器(执行器):测试或高级适配入口。
原生文件默认开启外键、WAL、NORMAL 同步和 5 秒 busy timeout。URI 会拒绝 authority、百分号编码、片段、多个查询串和重复 mode,避免权限检查路径与 SQLite 实际解码路径不一致。
参数、标识符与预编译
值只能放在参数列:
定 各行 为 数据库.查询(
「SELECT id, name FROM users WHERE name = ? AND age >= ?」,
【姓名,18】
).全部();表名、列名、排序方向与操作符不能作为参数。动态标识符应先通过业务白名单,再用 数据库.方言().引名(名称) 引用。
默认原生后端把 SQL 模板交给 SQLite 编译器,并通过原生 API 绑定值,不把值转换成 SQL 文字。高频模板应复用并显式关闭原生语句:
定 语句 为 数据库.预编译(
「INSERT INTO events(kind, payload) VALUES (?, ?)」
);
逐 事件 于 各事件 则
语句.执行(【事件【「种类」】,事件【「正文」】】);
终
言 语句.参数数();
语句.关闭();连接关闭会级联失效子语句。CLI 后端的 SQLite预编译 只是兼容外观,每次仍启动兼容执行器;绑定(SQL, 参数) 也只服务 CLI 与审计展示,不能让不可信 SQL 模板自动安全。
事务、保存点与批量
原生后端支持可交互事务查询:
定 事务 为 数据库.立即事务();
试 则
事务.执行(「UPDATE accounts SET balance = balance - ? WHERE id = ?」,【10,甲】);
事务.保存点(「credit」);
事务.执行(「UPDATE accounts SET balance = balance + ? WHERE id = ?」,【10,乙】);
事务.释放点(「credit」);
事务.提交();
救 所误 则
若 事务.是否活跃() 则
事务.回滚();
终
抛 所误;
终同一连接一次只能有一个顶层事务。保存点按后进先出释放;回滚至(名称) 后保存点仍存在,必须继续使用或释放。
批量执行(各语句) 把 SQL 文字或 {SQL, 参数} 放进一个立即事务。CLI 兼容事务会先安全绑定并缓存脚本,提交时一次执行;它在提交前不能返回事务内查询结果,也不持有真正的原生 statement 句柄。
连接池
言舟自身不新增池 API;使用言库的通用连接池组合连接工厂:
引「包:言库」为 言库;
法 新连接() 则
归 言舟.打开(「data/应用.db」);
终
定 池配置 为 言库.连接池配置()
.最小(1)
.最大(8)
.取得超时(2000)
.健康间隔(30000);
定 池 为 言库.连接池(新连接,池配置);
定 租约 为 池.取得();
言 租约.查询(「SELECT 1」,【】).标量();
租约.释放();
池.关闭平缓(5000);共享内存库需要命名 file: URI 与 cache=shared;多个普通 打开内存() 连接互相不可见。池不会替应用选择 WAL、处理长写事务,也不会自动重放失败写入。
结构反射
逐 表 于 数据库.表清单() 则
言 表;
终
定 结构 为 数据库.表结构(「users」);
言 结构【「列」】;
言 结构【「索引」】;
言 结构【「外键」】;表结构 覆盖 main/temp 表与视图、列、复合索引的索引列和外键动作;缺失表返回 存在 = 假 的稳定空结构。表名作为反射查询参数传入,不通过错误消息猜测结构。
版本化迁移
定 各迁移 为 【
言舟.迁移(
1,
「创建用户」,
「CREATE TABLE users(id INTEGER PRIMARY KEY)」,
「DROP TABLE users」
),
言舟.迁移(
2,
「增加姓名」,
「ALTER TABLE users ADD COLUMN name TEXT」,
「ALTER TABLE users DROP COLUMN name」
)
】;
定 迁移器 为 言舟.默认迁移器(数据库);
言 迁移器.检查(各迁移);
言 迁移器.干运行升级(各迁移);
迁移器.升级(各迁移);默认登记表为 _yanxu_migrations。版本必须严格递增;SHA-256 覆盖版本、名称、升级和降级 SQL。升级/回退在 BEGIN IMMEDIATE 写锁中重读历史,并把 DDL 与登记原子提交。已应用定义缺失、名称或内容漂移、不可逆回退都会被拒绝。
旧登记没有校验和时,先审计实际结构和历史,再显式调用 采用旧校验和(各迁移);它只补登记,不会猜测历史 SQL 是否执行过。
言据与 JSON1
| 策略 | SQLite 存储 | 语义 |
|---|---|---|
规范文本 | TEXT 中的规范 .yj 文本 | 跨数据库保真与稳定交换 |
原生结构 | JSON1 可查询的 JSON 文本 | 读回恢复言序值,可做路径查询 |
定 写入值 为 数据库.言据写入值(资料,「原生结构」);
数据库.执行(「INSERT INTO profiles(data) VALUES (?)」,【写入值】);
定 条件 为 数据库.言据路径(「data」,【「等级」】).至少(10);
定 表达式 为 条件.转典();
定 各行 为 数据库.查询(
(「SELECT data FROM profiles WHERE 」 加 表达式【「SQL」】),
表达式【「参数」】
).全部();JSON 路径段和比较值也作为参数。JSON1 按运行时探测;不可用时返回能力错误,不会退化为全表内存过滤。SQLite JSON 文本不是规范言据文本,两种策略的磁盘格式不能互相冒充。
权限与安全边界
| 场景 | 顶层应用所需权限 |
|---|---|
| 原生文件/URI 数据库 | 对实际路径的 文件 + 原生扩展 = true |
| 原生内存/临时数据库 | 原生扩展 = true;无需应用文件权限 |
| CLI 文件数据库 | 实际路径 文件 + 进程 = true + 原生扩展 = true |
ABI v2 原生扩展与宿主进程拥有相同操作系统权限,不是文件沙箱。应用不要绕过公开打开入口直接调用 ABI。迁移 SQL、动态标识符和 CLI 程序路径都属于受信任配置边界。
支持矩阵与明确限制
| 后端/目标 | 1.0 状态 |
|---|---|
| bundled SQLite 3.53.2 | 默认原生后端,已固定构建与真实消费者验证 |
| 系统 SQLite 3.38+ | 显式 CLI 兼容后端;需要 -json 等能力 |
| macOS x86-64 / ARM64 | 提供固定 ABI v2 制品 |
| Linux glibc x86-64 / ARM64 | 提供固定 ABI v2 制品 |
| Windows x86-64 / ARM64 | 提供固定 ABI v2 制品 |
- 原生 SQL 最多 1 MiB、参数最多 65,536 个;单次结果最多 100,000 行、1,024 列和 16 MiB。
- busy timeout 只控制 SQLite 锁等待,不是总查询截止;1.0 不提供异步查询取消。
- 1.0 没有言舟专用连接池,使用言库通用池。
- CLI 每次请求启动进程,性能较低;事务提交前不能查询,也没有真正预编译资源。
- URI 权限规则刻意拒绝部分 SQLite 合法但难以一致授权的 URI 形式。
- SQLite 不支持所有在线 DDL;复杂改列、外键和检查约束变更应使用经验证的重建表迁移。
错误以 YANZHOU_、YANKU_SQLITE_ 等稳定代码分类。仓库与 1.0.0 Release:yanxulang/yanxu-sqlite。