新闻详情

新闻详情

首页 / 资讯中心 / 详情

libSQL 中 vendored rusqlite 的演进史:从 Changelog 看类型系统、事务与回调 API 的设计变迁

发布时间:2026/9/13 23:55:17来源:尧图网络
libSQL 中 vendored rusqlite 的演进史:从 Changelog 看类型系统、事务与回调 API 的设计变迁
libSQL 中 vendored rusqlite 的演进史从 Changelog 看类型系统、事务与回调 API 的设计变迁【免费下载链接】libsqllibSQL is a fork of SQLite that is both Open Source, and Open Contributions.项目地址: https://gitcode.com/GitHub_Trending/li/libsql导读本文以 libSQL 仓库中 vendored 的 rusqlite包名为libsql-rusqlite的 Changelog.md 为核心脉络逐版本梳理这个 Rust SQLite 绑定库从 2014 年到 2018 年的 API 演进过程。你将理解ToSql/FromSql类型系统为何走向安全化设计、Transaction/Savepoint的 drop 行为契约、prepare_cached语句缓存的默认容量、functions/backup/blob/hooks/limits等 Cargo feature 的能力边界以及 rusqlite 在 libSQL 工作区中的实际启用配置。读完本文你能基于 Changelog 快速判断各版本 API 的破坏性变更点并学会在 libSQL 生态中使用这套绑定。一、Changelog 与 libSQL 的 vendored 关系rusqlite 是 Rust 生态中最流行的 SQLite 安全封装而 libSQL 作为 SQLite 的开源分支在 Cargo.toml 中把 rusqlite 作为工作区成员以path vendored/rusqlite方式引入并在 工作区依赖 中重命名为libsql-rusqlite版本为0.10.0-pre.4rusqlite { package libsql-rusqlite, path vendored/rusqlite, version 0.10.0-pre.4, default-features false, features [ libsql-experimental, column_decltype, load_extension, modern_sqlite, functions, limits, hooks, ] }注意两点default-features falselibSQL 按需裁剪 feature而不是启用 rusqlite 的全部默认能力显式启用了functions用户自定义函数、limits运行时限制、hooks提交/回滚/更新回调、load_extension扩展加载、modern_sqlite要求较新 SQLite与 libSQL 特有的libsql-experimental实验特性。从 vendored/rusqlite/Cargo.toml 可以看到该 vendored 包的[lib]名仍为rusqlite即依赖方写use rusqlite即可但包名已被 libSQL 接管。这也解释了为什么 Changelog 中所有 0.14.0 及更早的版本记录都出自上游 rusqlite——本仓库中的 Changelog.md 开头明确指出“0.15.0 及以后的版本请参见 Releases 页面”而 0.15.0 之前的完整历史都保留在本文件中。二、类型系统与错误模型的两次大重构2.1 FromSql / ToSql 从 unsafe 走向安全 traitrusqlite 早期0.0.x0.7.x的ToSql/FromSql需要实现者接触底层 unsafe 方法这是新手最容易踩坑的地方。0.8.02016-12-31是一次关键转折FromSql被重新设计只要求实现一个安全方法取代原先“实现一个或两个 unsafe 方法”的定义ToSql同样可以在不用unsafe的情况下实现且实现者可以自由选择返回借用值还是所有权值Error枚举的部分变体携带了更多上下文例如FromSqlConversionFailure现在同时包含列索引和 SQLite 返回的类型。从当前仓库的 types/from_sql.rs 与 types/to_sql.rs 可以看到trait 已是完全安全的形态并且 types 目录下分别以chrono.rs、serde_json.rs、time.rs、url.rs等模块为chrono、serde_json、time、url等可选依赖提供类型转换实现——这正是 0.7.2 中“新增 serde_json / chrono 序列化支持”在源码层面的落点。2.2 数值类型的边界i64 是桥梁Changelog 在多个版本中反复强调整数类型映射0.9.22017-01-22修复i32的FromSql在底层值越界时应返回错误而非静默截断0.9.2 同时新增i8、i16、u8、u16、u32的FromSql/ToSql实现并明确说明不提供u64因为 SQLite 与 Rust 通信的桥接类型是i64u64的取值区间无法被i64完整表示0.11.02017-04-06为isize补上了实现并同样在文档中解释为什么usize与u64被排除。这是一个至今仍影响所有 rusqlite 使用者的约束从数据库读出无符号大整数时需要自行考虑溢出处理。2.3 列索引 / 参数索引 / 影响行数全面改为 usize0.14.02018-08-17做了一组破坏性变更把列索引/列数、参数索引/参数数、行变更数/行数等类型全部从i32替换为usize。这些改动让 API 与 Rust 的切片索引习惯对齐避免负索引等非法值。此外 0.14.0 还要求标量函数必须Send且static为多线程环境下安全执行用户定义函数奠定基础。2.4 SqliteError 从 struct 变为 enum0.6.02015-12-17是错误模型的重大调整SqliteError由结构体改为枚举。此前该类型同时背负“底层 SQLite 错误码/消息”和“Rust 层错误”两类语义0.6.0 将其拆分为SqliteFailure变体携带 SQLite 错误码同时给出 Rust 友好的枚举其他变体仅表达 rusqlite 自身层面的错误。由于结构体形态被打破SqliteError不再实现PartialEq。同版本还统一去掉了Sqlite前缀SqliteConnection→Connection、SqliteStatement→Statement、SqliteOpenFlags→OpenFlags、SqliteTransaction→Transaction等旧名称仍导出但标记为 deprecated。三、事务、Savepoint 与 Drop 行为契约3.1 mut Connection 的编译期嵌套防护0.7.22016-05-19规定从Connection创建事务、从Transaction创建 savepoint 现在要求mut self以正确表达“同一连接上的事务天然嵌套互斥”。同时Transaction实现DerefTarget Connection使事务对象可以直接调用Connection的方法。当前 transaction.rs 中的Transaction::new仍保留mut Connection签名并提供了new_unchecked供确实需要绕过编译期检查的场景例如RcConnection共享连接。源码注释明确写道“即使我们不修改连接也取mut Connection以防止同一连接上出现嵌套事务”。Connection::unchecked_transactiontransaction.rs把检查推迟到运行时——测试test_unchecked_nesting验证了嵌套时会返回含 “transaction” 字样的错误。3.2 DropBehavior从 set_commit/set_rollback 到统一枚举0.7.2 用Transaction::set_drop_behavior取代了原先的set_commit与set_rollback0.14.0 又新增DropBehavior::Panic用于“强制显式 commit 或 rollback”的开发期约束。当前实现的 DropBehavior 枚举 包含四种取值取值行为Rollback默认值drop 时回滚Commitdrop 时提交Ignore不提交也不回滚事务/savepoint 保持打开需谨慎使用Panicdrop 时 panic用于开发期强制显式收尾Transaction::finish_transaction.rs在Drop实现中被调用先检查is_autocommit()判断事务是否已结束再按drop_behavior分派Commit分支在提交失败时回退为回滚避免留下悬挂事务。这与 0.14.0 修复的“提交失败未处理导致数据库处于不可用状态”bug#366直接相关。3.3 Savepoint 与 Transaction 的语义差异0.7.2 中Transaction::savepoint()改返回Savepoint而非另一个Transaction。关键区别在 Savepoint 实现Savepoint::rollback执行ROLLBACK TO namesavepoint 仍保持激活可以再次回滚或提交Savepoint支持任意深度嵌套depth字段递增默认名称形如_rusqlite_sp_{depth}也可通过savepoint_with_name/with_name自定义Drop时未提交的 savepoint 按DropBehavior处理已提交的committed true直接跳过。测试test_savepoint用三层嵌套 savepoint 演示了“内层提交后被外层回滚抹除”的语义值得作为理解 savepoint 行为的参考样例。四、语句缓存与查询便利方法4.1 prepare_cached 与 LRU 缓存容量0.7.2 引入Connection::prepare_cached并配套set_prepared_statement_cache_capacity默认容量为16超出后会重新 prepare。当前 cache.rs 用hashlink::LruCacheArcstr, RawStatement实现prepare_cached命中缓存时直接复用底层 SQLite 语句句柄未命中则走conn.prepare并记录缓存键键是sql.trim()后的 SQL 文本语句归还缓存时执行stmt.clear_bindings()清除绑定确保下一次复用不受残留参数影响CachedStatement::discard()可阻止语句回到缓存self.stmt Noneflush_prepared_statement_cache一键清空。test_set_capacity验证了容量设为 0 时缓存不再保留任何语句。0.7.2 中还修复了一个与此相关的 bug使用缓存的 prepared statement 会导致连接关闭时返回DatabaseBusy——因为语句仍在缓存中未被 finalize。4.2 query_row / query_map / query_and_then 族Changelog 记录了查询 API 的持续扩展0.1.0query_row改为返回Result不再 unwrap新增query_map与get_checked0.3.0新增query_row_and_then、query_and_then允许闭包返回Result参与失败传播0.7.2新增query_map_named、query_and_then_named支持命名占位符?name/:name/name0.7.2 同期把RowIndextrait 引入Row::get列既可按下标取也可按名称取Statement::column_index在 0.14.0 中改为大小写不敏感。4.3 便捷方法insert 与 exists0.7.2 为Statement新增insert执行插入并返回该行的 row ID。0.7.3 修复了它“连续插入不同表、恰好返回相同 row ID 时误报失败”的问题#171说明其内部用变更行数判断成功跨表场景下不可靠exists判断查询是否能取到至少一行适合存在性检查。五、回调与钩子update / commit / rollback / authorizer5.1 三大数据钩子0.14.0 实现了sqlite3_update_hook、sqlite3_commit_hook、sqlite3_rollback_hook的绑定并修复了free_boxed_hook对fn函数指针而非闭包不生效的问题。当前 hooks.rs 提供的公共 API 为commit_hook(OptionF)F: FnMut() - bool返回true触发回滚rollback_hook(OptionF)F: FnMut()在事务回滚时被调用update_hook(OptionF)F: FnMut(Action, str, str, i64)回调参数依次为更新动作SQLITE_INSERT/SQLITE_UPDATE/SQLITE_DELETE、数据库名、表名、被更新行的 ROWIDprogress_handler与authorizer也在同模块中实现。底层实现如 commit_hook 的 FFI 封装把闭包装箱为Box::into_raw传入 C 回调并用catch_unwind隔离 panic由于sqlite3_commit_hook不支持xDestroy析构回调释放逻辑被保存在InnerConnection.free_commit_hook中换钩子时释放旧闭包。remove_hookshooks.rs一次性清除全部钩子。模块内的测试用例可直接作为使用示范test_update_hook在INSERT INTO foo VALUES (lisa)后断言Action::SQLITE_INSERT、数据库名main、表名foo、row_id 为 1。5.2 authorizer 与细粒度授权hooks.rs 的 authorizer 在语句 prepare 阶段被调用回调接收AuthContextc包含action: AuthActionc、database_name、accessor最内层触发器或视图顶层 SQL 为None。AuthAction覆盖了CreateTable、DropTable、Insert、Read、Pragma、Savepoint、Function等全部 SQLite 授权动作返回值Authorization三态为Allow/Ignore/DenyAllowSQLITE_OK放行IgnoreSQLITE_IGNORE不放行也不报错例如让某列读出NULLDenySQLITE_DENY触发错误。test_authorizer展示了经典用法拦截对private列的读取Ignore使该列变为NULL、拒绝DROP TABLE、并在移除 authorizer 后验证PRAGMA user_version1恢复正常执行。5.3 busy 处理busy_timeout 与 busy_handler0.14.0 增加了sqlite3_busy_timeout与sqlite3_busy_handler绑定。当前 busy.rs 中busy_timeout(Duration)把毫秒数传给sqlite3_busy_timeout超时会被 busy 处理程序按“累计睡眠”方式处理传入 0 会关闭所有 busy handlerbusy_handler(Optionfn(i32) - bool)自定义回调参数为同一锁事件下已重试次数返回true继续重试、false立即返回SQLITE_BUSY注意它接受的是fn函数指针而非闭包。源码注释指出新建连接的默认 busy 超时为 5000ms该默认值未来可能调整。test_default_busy则演示了默认行为下另一连接持有EXCLUSIVE事务时本连接读库会得到ErrorCode::DatabaseBusy。六、连接、版本与初始化检查6.1 open 与 open_in_memory 的分工0.0.102015-02-23是破坏性变更open从接受str改为接受Path并新增独立的open_in_memory构造器。当前仓库中大量测试如 hooks、busy、transaction 模块都用Connection::open_in_memory()快速构建内存数据库正是这一分工的延续。6.2 运行库与编译库的版本一致性检查0.10.02017-02-28引入两项初始化检查线程模式检查当运行时 SQLite 为单线程编译/配置时连接尝试将失败对 3.6.x 的 SQLite 会自动执行 SQLite 初始化失败则 panic版本一致性检查首次连接前确认运行时 SQLite 版本不早于编译时版本可调用 unsafe 的rusqlite::bypass_sqlite_version_check()跳过。同版本还规定SQLite 版本低于 3.6.8 时直接 panic且部分 feature 需要足够新的 SQLite 才能编译。这也是 vendored/rusqlite/Cargo.toml 中众多 feature 注释里标注 SQLite 版本门槛如blob需 3.7.4、functions需 3.7.3、window需 3.25.0的原因。当前实现可通过version()与version_number()见 version.rs在运行时查询所用 SQLite 版本。6.3 打开标志与自动行为0.2.02015-07-26起新连接默认带上SQLITE_OPEN_NO_MUTEX与SQLITE_OPEN_URI标志——前者关闭互斥锁以提升单线程使用性能后者允许 URI 形式的数据源如file:...?modememory。0.3.0 移除了get_opt改用get_checked0.1.0 引入让 SQLite 对列做基本类型检查并返回错误而非 panic0.3.1 开始执行语句后尽早 reset遵循 SQLite 官方“滚动游标”建议。七、Cargo feature 地图从 Changelog 到 Cargo.tomlChangelog 中反复出现的 feature 在 vendored/rusqlite/Cargo.toml 中都能找到对应定义与版本门槛汇总如下Feature引入版本能力SQLite 版本门槛load_extension0.0.10加载 SQLite 扩展依赖编译选项backup0.6.0在线备份 API3.6.11blob0.6.0BLOB 增量 I/O3.7.4functions0.6.0标量/0.7.2聚合用户自定义函数3.7.3trace0.5.0SQLite 日志/跟踪/性能钩子3.6.23limits0.10.0运行时限制limit/set_limit—hooks0.14.0 实现update/commit/rollback 钩子—unlock_notify0.14.0解锁通知—sqlcipher0.13.0链接 SQLCipher 而非 SQLite—vtab/csvtab/series/array0.7.2 后虚拟表支持3.7.7 起session—SQLite session 扩展3.13.0window—窗口函数3.25.0modern_sqlite—声明使用较新 SQLite3.14.0 之后3.14.0bundled0.8.0从源码编译 SQLite 而非链接系统库—libSQL 工作区Cargo.toml实际启用了其中的functions、limits、hooks、load_extension、modern_sqlite与column_decltype并额外叠加了 libSQL 分支特有的libsql-experimental及传递性的libsql-wasm-experimental后者在 libsql-server/Cargo.toml 的wasm-udfsfeature 中被引用用于 WASM 用户定义函数。libsql-server的debug-toolsfeaturelibsql-server/Cargo.toml还会开启rusqlite/trace用于排查 SQL 执行问题。八、从历史到当下给开发者的迁移与使用要点综合 Changelog 与源码可以总结出几条对当前使用libsql-rusqlite开发最有价值的经验类型映射记住i64桥梁不要依赖u64的直接FromSql/ToSql大整数需要自行设计存储与溢出策略Row::get的列索引类型为usize命名取列对大小写不敏感。事务默认回滚显式 commitTransaction/Savepoint的默认DropBehavior是Rollback开发期可用DropBehavior::Panic强制所有路径显式收尾savepoint 回滚后仍保持激活这是与事务最大的行为差异。缓存语句按 SQL 文本为键prepare_cached依赖精确trim 后的 SQL 匹配动态拼接 SQL 会频繁 miss容量默认 16可通过set_prepared_statement_cache_capacity调整discard()可强制语句不入缓存。钩子回调中避免 panic底层用catch_unwind包裹闭包panic 会被吞掉commit 钩子返回 false 等价语义业务上应把钩子当作“通知”而非“业务主逻辑”。feature 即版本契约启用session、window、vtab等特性前确认目标 SQLite 满足 Cargo.toml 中标注的最低版本否则会编译失败。本仓库的 libsql/examples如 example.rs、transaction.rs与 vendored/rusqlite/tests 中保留了大量可直接运行的示例与集成测试可作为上手libsql-rusqlite的补充参考而 vendored/rusqlite/src 下的transaction.rs、cache.rs、hooks.rs、busy.rs、limits.rs、types/则是验证本文所有论断的第一手源码。本文内容基于 libSQL 仓库中 vendored/rusqlite/Changelog.md 的历史版本记录并结合 vendored/rusqlite/src 当前源码与工作区 Cargo.toml 配置交叉验证文中所有版本门槛、默认值均以当前仓库实际内容为准。【免费下载链接】libsqllibSQL is a fork of SQLite that is both Open Source, and Open Contributions.项目地址: https://gitcode.com/GitHub_Trending/li/libsql创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

[数字安全]PDR 与 P2DR 资讯安全模型比较:核心差异、应用场合与实战落地 2026/9/14 0:55:22

[数字安全]PDR 与 P2DR 资讯安全模型比较:核心差异、应用场合与实战落地

很多做安全的人第一次看到 PDR 和 P2DR,反应都差不多:不就是多了一个 P 吗? 这个 P 还真不是凑数的。它把安全体系从“防护、检测、响应”三个动作,变成“策略驱动下的防护、检测、响应”闭环。前者更像一套技术组合,后…

阅读更多 →
ECDSA 椭圆曲线签名:比 RSA 更短却更安全 2026/9/14 0:55:22

ECDSA 椭圆曲线签名:比 RSA 更短却更安全

ECDSA 椭圆曲线签名:比 RSA 更短却更安全同样 128 位安全强度,RSA 密钥要 3072 位,ECDSA 只要 256 位——签名还快一到两个数量级。但它有一条致命红线:nonce 一旦重复,私钥瞬间泄漏。今天讲透原理与这条红线。一、背景…

阅读更多 →
推荐系统为什么必须分成召回和排序两步来做 2026/9/14 0:55:22

推荐系统为什么必须分成召回和排序两步来做

推荐系统为什么必须分成召回和排序两步来做一亿件商品、200 毫秒延迟,推荐系统凭什么敢答应?答案是一个被算力逼出来的架构:召回先快筛,排序再精算。今天把这条分层逻辑讲透。一、背景与痛点 把推荐系统想象成一个深夜营业的商场导…

阅读更多 →
目标检测里的 NMS:为什么同一物体只留一个框 2026/9/14 0:55:22

目标检测里的 NMS:为什么同一物体只留一个框

目标检测里的 NMS:为什么同一物体只留一个框同一只猫,检测器却吐出十几个重叠的框——从一堆框里优雅地留下唯一答案,靠的就是 NMS。今天用几十行 numpy 把它的原理、公式和工程坑一次讲透。一、背景与痛点 你跑过一次目标检测模型就会发现一…

阅读更多 →
GRPO 为什么不用价值网络,却能训出推理模型 2026/9/14 0:55:22

GRPO 为什么不用价值网络,却能训出推理模型

GRPO 为什么不用价值网络,却能训出推理模型 同一道题让模型多答几遍,谁好谁坏自己就浮出来了——GRPO 靠这个朴素想法,把 PPO 的价值网络整个省掉。 一、背景与痛点 想让大模型真正学会解数学题、写对代码,光靠监督微调常常不够&…

阅读更多 →
Python运维相关的笔试题及答案 2026/9/14 0:52:22

Python运维相关的笔试题及答案

笔试题及答案项目代码本文档是一套笔试题库, 其中包含详细答案, 题型包含选择题, 解答题以及编程题, 全面覆盖了基础知识点。2023年《网络建设与运维》国赛脚本文件及导出答案视频需要参赛的人员要对最少一种脚本语言做到熟悉, 并且能够领会脚本里和网络有关的指令, 从而迅速地…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞