modernc.org/sqlite:Driver 支持注册函数与模块,vtab 行为变更
sqlite: let a caller-constructed Driver register its own functions, collation...
Go 开发者若用 modernc.org/sqlite 且通过 vtab.RegisterModule 注册模块,升级后行为会变:在自定义 Driver 上注册的模块不再全局可见,可能触发 "no such module"。建议检查代码中 vtab.RegisterModule 的调用方式,确认是否依赖旧行为。
Driver 持有四类注册状态,但只有连接钩子可以挂载到构造出的实例上。函数和排序规则只能通过包级 API 访问,模块只能通过包级 driver 访问,因此构造出的 Driver 是半成品的:其 modules 字段通过包级实例读写,使其成为披着实例字段外衣的进程全局状态。这是 #254 的增量部分,下面列出一个狭窄而明显的例外:- registerFunction 和 registerCollation 成为 *Driver 的方法。包级 RegisterFunction、RegisterScalarFunction、RegisterDeterministicScalarFunction 和 RegisterCollationUtf8 继续针对包级 driver,现在明确写出,而不是依赖名为 d 的接收者遮蔽同名包变量。newDriver 更名为 defaultDriver,因为它读起来像构造函数,但返回的是单例。- Driver 新增 RegisterFunction、RegisterScalarFunction、RegisterDeterministicScalarFunction、RegisterCollationUtf8 和 RegisterModule,以及前四个的 Must* 变体,每个都仅在该 Driver 上注册。零值 Driver 仍可使用:映射按需创建,因为构造出的 &Driver{} 中映射为 nil,而包级实例是用 make 构建的。Driver 上的互斥锁使并发注册安全,因此 *Driver 可以分发给多个包,让它们从 init 函数中填充。- 连接现在接收包级 driver 上注册的模块与打开该连接的 Driver 上注册的模块的并集。包级集合无条件应用,这是自模块支持添加以来每个连接都接收到的,因此 #254 警告的隔离性变更不在此处进行。两个集合中均存在的名称解析为包级实现。- 传递给 sqlite3_create_module_v2 作为 pAux 的 ID 按 (Driver, name) 对分配,而非按名称分配。它是每个蹦床函数分发的依据,按名称分配的 ID 会使两个 Driver 注册相同模块名时共享一个条目,最后一次注册会在进程范围内并追溯性地影响已打开的连接。- vtab.RegisterModule 尊重其 db 参数:非 nil 的 db 在该 driver 实现新的 vtab.ModuleRegisterer 时注册到其背后的 driver,nil 的 db 则继续针对本包注册为 "sqlite" 的 driver。对于在“sqlite”上打开的数据库,两者是同一个驱动,因此结果不变。例外情况:vtab.RegisterModule(db, ...) 中,如果db是在调用者构造的Driver上打开的,以前会忽略db参数并落在“sqlite”驱动上,从而影响到进程中的每个连接。现在它仅落在构造的驱动上,因此之前能解析此类模块的sql.Open("sqlite")连接现在会得到“no such module”错误。同样的调用也是现有代码能在构造的Driver和包级Driver上同时持有模块名的唯一途径,因此上述冲突规则是例外情况的第二个更窄的部分,而非延续。以前,两个注册中先注册的获胜,后注册的因已注册而被拒绝;现在,无论注册顺序如何,包级实现都在构造的Driver的连接上获胜。没有与顺序无关的规则能重现旧行为,而且遇到这种情况本身就意味着程序忽略了旧版本返回的错误。还有两个较小的偏差:Driver.RegisterModule对此类冲突不报告错误,且vtab.RegisterModule在未实现检查之前验证其名称和模块参数,因此在此驱动之外返回ErrNotImplemented的空名称调用现在会返回“vtab: module name must be non-empty”。测试覆盖了新注册、拒绝重复、两个构造的Driver之间以及与包级Driver之间的隔离——包括两者注册相同模块名时,在第二个Driver打开连接之前固定一个连接进行测试——并发注册通过竞态检测器,全局注册的模块仍能到达构造的Driver,以及db参数选择驱动。行为保持特性、同名情况和并发声明均通过故意破坏并确认测试失败来验证。更新 #254
更进一步:量化金融体系
看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力