扩展库 / sqlite
sqlite
数据库内置 SQLite 的本地数据库,提供 Database、Statement、精确状态码及 C 接口。支持内存库、UTF-8 文件路径、事务与二进制数据,不依赖额外数据库 DLL。
2026-10-30:修复两个 C 借用型列出口在首错后继续分配空文本、二次 OOM 覆盖首错的问题。 与已有拥有型出口使用相同检查;公开 ABI、正常复制和释放责任不变。 Windows复跑72项、Linux71阶段及44原型/45常量通过;历史Linux无诊断退出及本轮一次Windows AOT截断仍待定位,保持R,不据此签收完整发布。
参数绑定与查询
import sqlite
auto db = sqlite.memory()
assert db.execute("create table people(name text)")
auto insert = db.prepare("insert into people values(?)")
assert insert.bind(1, "O'Reilly") == sqlite.SQLITE_OK
assert insert.done()
insert.finalize()
var rows = db.query("select name from people")
println(rows[0]["name"])
参数从 1 开始,列号从 0 开始。绑定复制数据,不要求调用方保持原字符串或 Buffer 存活。
XLang 的路径、VFS 名、SQL 和普通文本绑定会在调用零结尾 C API 前拒绝内嵌 NUL,抛出 ValueError,不会执行 SQL 前缀或静默截断绑定。含 NUL 的 TEXT 使用 bind_text_bytes / column_text_bytes,BLOB 使用 Buffer;成对完整范例见 examples/text_bytes.xl 与 text_bytes_c.c。
2026-10-28:Windows 49 项完整门禁、Linux ASan/UBSan、分配故障、线程、26 组输入拒绝及双语 JIT/AOT 通过。旧 Linux 无诊断退出仍未定位,保持待稳定性收口,不能将本次通过解释为该风险已修复。
Database
| 接口 | 合同 |
|---|---|
memory() / open(filename) / open_v2(filename, flags, vfs) | 独立内存库、读写创建文件、显式打开模式;空 vfs 使用 SQLite 默认值。 |
valid() / close() / close_v2() | 查询与释放连接。close 遇到未释放语句返回 SQLITE_BUSY 并保留连接;close_v2 延迟到语句释放后销毁。 |
execute(sql) / exec_code(sql) / last_error() | 成功布尔值、精确 SQLite 返回码、当前连接的 SQL 错误文本。 |
prepare(sql) / query(sql) | 拥有型语句、全部行字典数组。prepare 只接受一条语句;query 失败抛错,不返回部分成功。 |
begin() / commit() / rollback() | 事务操作,返回成功布尔值。 |
changes() / total_changes() / last_insert_rowid() | 64 位计数与行号;另有 last_insert_rowid_text()。 |
busy_timeout(milliseconds) | 设置锁等待上限;0 表示不等待,不自动重试整个事务。 |
prepare 只扫描第一条语句之后的空白、空语句和注释,不为检查尾部再次编译 SQL,避免被拒绝的额外 PRAGMA 改变连接配置。第一条语句仍遵守 SQLite 自身语义:部分 PRAGMA 在编译时就生效,不能将 prepare 当作无副作用或只读 SQL 校验器。
Statement
| 接口 | 合同 |
|---|---|
bind(index, int|float|string|Buffer) / bind_null(index) | 保留 64 位整数;Buffer 是 BLOB,NULL 与空值分开。 |
bind_text_bytes(index, Buffer) / bind_blob_text(index, string) | 精确长度 TEXT、把普通文本字节写为 BLOB。 |
step() / row_ready() / done() | 每次推进一次。step 返回状态码;两个布尔便利方法在错误时抛出 RuntimeError。 |
column_count() / column_name(column) | 元数据,可在 step 前读取。 |
column_type/int/float/text/blob/text_bytes/blob_text(column) | 读取当前行;必须先得到 SQLITE_ROW,列越界或没有当前行会报错。 |
value(column) / row() | 动态值、列名字典。BLOB 是 Buffer,SQL NULL 是 null;重复列名请用 SQL AS 区分。 |
reset() / clear_bindings() / last_error() | 重执行时保留绑定、清空绑定、当前语句所属连接的 SQL 诊断。 |
valid() / finalize() | 重复释放是成功空操作;释放后的其他对象操作报 RuntimeError。 |
二进制与寿命
列文本、列名、诊断和 rowid 文本直接返回拥有型 string,不再经过可空辅助函数复制正文。2026-10-28 的 32 组分配预算检查与 Windows/Linux JIT/AOT 覆盖正常结果、原生分配失败、SQL NULL 和结果寿命。为了让字符串在语句关闭后仍可使用,SQLite 借用文本到 XRT 拥有内存的一次副本仍然存在,不能把该优化称为整条 SQL 调用零开销。
auto stmt = db.prepare("select x'00ff2a'")
assert stmt.row_ready()
Buffer bytes = stmt.column_blob(0)
stmt.finalize()
// bytes 拥有副本,语句释放后仍可访问。
assert bytes.len() == 3 and bytes[0] == 0
含 NUL 的 TEXT 使用 bind_text_bytes/column_text_bytes;普通字符串读取会拒绝截断。 SQL NULL 与零长度 BLOB 不同,使用 column_type 或 value 区分。大结果集用 Statement 逐行读取,query 会物化全部行。
对象赋值共享身份,不复制句柄,不声明 copy/clone 能力。Database(point) 和 Statement(point) 接管原始句柄, 不增加引用;不得重复接管或从 C 再次释放。同一对象的多步操作由调用方串行化,不支持一边读列一边并发关闭/step/reset。
新增 transactions.xl/transactions_c.c 六行固定输出:唯一约束失败、reset 的上一轮错误码、清空绑定、 显式回滚、语句复用、busy close 保留所有权、无当前行拒绝及关闭后的拥有型文本。C 和 XLang 均可直接 xl run/build, 不自动重试或隐式提交失败事务。两平台GCC、C直跑/独立EXE、XLang JIT/AOT与同一六行golden一致;Linux C另含ASan/UBSan/泄漏检查。
独立 C 首错测试共18组错误与5组正常输出 OOM:旧代码9项错误覆盖,新代码归零; 空 TEXT、SQL NULL 和空列名仍为成功内容,不能用“空串不分配”代替错误状态检查。 钩子仅用于独立原生进程,分配器回调必须活到所有内存释放,不能当成可卸载脚本范例。
模块级接口
sqlite3_* 使用薄绑定。普通 int 参数进入 C int 前检查范围,SQLITE_* 常量只读。 模块级 last_error/sqlite3_last_error 只读取当前 XRT 错误;SQL 状态码对应的诊断使用连接/语句 last_error。
available() as bool
version() as string
last_error() as string
sqlite3_last_error() as string
sqlite3_open(string filename) as point
sqlite3_open_v2(string filename, int flags, string vfs) as point
sqlite3_close(point db) as int
sqlite3_close_v2(point db) as int
sqlite3_exec(point db, string sql) as int
sqlite3_prepare_v2(point db, string sql) as point
sqlite3_step(point stmt) as int
sqlite3_finalize(point stmt) as int
sqlite3_reset(point stmt) as int
sqlite3_clear_bindings(point stmt) as int
sqlite3_bind_int(point stmt, int index, int value) as int
sqlite3_bind_int64(point stmt, int index, int value) as int
sqlite3_bind_double(point stmt, int index, float value) as int
sqlite3_bind_text(point stmt, int index, string value) as int
sqlite3_bind_blob_text(point stmt, int index, string value) as int
sqlite3_bind_blob(point stmt, int index, Buffer value) as int
sqlite3_bind_text_bytes(point stmt, int index, Buffer value) as int
sqlite3_bind_null(point stmt, int index) as int
sqlite3_bind_parameter_count(point stmt) as int
sqlite3_column_count(point stmt) as int
sqlite3_column_type(point stmt, int column) as int
sqlite3_column_int(point stmt, int column) as int
sqlite3_column_int64(point stmt, int column) as int
sqlite3_column_double(point stmt, int column) as float
sqlite3_column_text(point stmt, int column) as string
sqlite3_column_blob_text(point stmt, int column) as string
sqlite3_column_blob(point stmt, int column) as Buffer
sqlite3_column_text_bytes(point stmt, int column) as Buffer
sqlite3_column_bytes(point stmt, int column) as int
sqlite3_column_name(point stmt, int column) as string
sqlite3_errmsg(point db) as string
sqlite3_stmt_errmsg(point stmt) as string
sqlite3_errstr(int rc) as string
sqlite3_extended_errcode(point db) as int
sqlite3_changes(point db) as int
sqlite3_total_changes(point db) as int
sqlite3_last_insert_rowid_text(point db) as string
sqlite3_last_insert_rowid(point db) as int
sqlite3_busy_timeout(point db, int milliseconds) as int
sqlite3_libversion() as string
sqlite3_libversion_number() as int
open(string filename) as Database
open_v2(string filename, int flags, string vfs) as Database
memory() as Database
C 使用
公开桥接头是 include/sqlite_native.h,上游完整 C 头是 third_party/sqlite3.h。
句柄必须来自同一份 SQLite。借用文本副本保存至 XRT 临时区 clear/rewind;返回的 xbuffer 由 C 调用方 xrtBufferDestroy。
成对范例:examples/extlibs/sqlite_basic.xl 与
extlibs/sqlite/examples/basic.c,C 范例可直接 xl run 或 xl build。底层状态码入口保留 SQLite 返回码,高层 query 不吞掉 SQL 错误。
专项验证
2026-10-29:在原有149个 SQLite 分配点之外,新增当前行的五类列访问矩阵,实际覆盖 int64/float 转文本及 UTF-16 存储转 UTF-8 字符串/Buffer 的四条 SQLite OOM 路径。故障保留 MemoryError/SQLITE_NOMEM,释放语句后连接可恢复,最终 SQLite 内存归零,XRT 活动数量/字节回到基线。当前 vendor 在 step 阶段展开 zeroblob,因此其4096字节读回检查不冒充列访问 OOM。新增 examples/column_storage.xl 与 examples/column_storage_c.c,展示 UTF-16 存储、UTF-8结果、完整int64文本和独立结果寿命;可直接 xl run 或 xl build。Windows 默认61项、44原型、45常量及 Linux 完整 ASan/UBSan/JIT/AOT 门禁通过,双语范例与 GCC/TCC 输出一致。未改实现、vendor或主线;历史 Linux 无诊断退出风险仍待定位。
Windows 37 项检查通过:44 个生成原型、45 个常量、SQLite 的 149 个分配故障点、 XRT Buffer 与临时文本分配失败、四个独立线程、中文路径/锁竞争和 C/xlang JIT/AOT/GCC 范例输出对照。 Linux 包级门禁现覆盖 C ASan/UBSan、分配故障与线程、中央/边界/文件 XLang JIT/AOT、公开双语范例的 JIT/AOT 和独立 GCC 固定输出对照。
2026-10-26:当前 Linux release/xl 完整门禁通过。Windows 专项门禁复验覆盖 37 项检查、44 个生成原型、45 个常量及 C/XLang 成对范例。数据库和语句析构只释放原生句柄,不再写入正在退役的对象字段;显式 close/finalize 保持幂等。此前的 XLIR ABI 错误属于旧发布物记录。
2026-10-28:尾部 PRAGMA 副作用的 C/XLang 红例修复后通过,另验 510 组单字节尾部与上游对照、授权回调、注释和 BOM 边界。最终 Windows/Linux 默认完整门禁通过,成对范例展示拒绝额外 SQL 后连接仍可写,固定输出不变。此前一次 Linux 门禁无诊断退出根因仍未知,暂列待定位风险;脚本现保留失败命令、原始状态及现场,不因最终复跑通过而关闭该风险。
范围不包含断电恢复、网络文件系统、跨进程 WAL 故障矩阵、32 位/ARM 或性能认证。 包装尚未提供数据库加密、异步线程池、自动事务重试、备份/增量 BLOB、高级回调或自定义 SQL 函数。