ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

drizzle-orm 0.44.5 版本解析:durable-sqlite `.one()` 修复与 SQLite blob 列的跨环境支持强化

2026/9/19 1:18:29 拓冰建站 浏览量
drizzle-orm 0.44.5 版本解析:durable-sqlite `.one()` 修复与 SQLite blob 列的跨环境支持强化 drizzle-orm 0.44.5 版本解析durable-sqlite.one()修复与 SQLite blob 列的跨环境支持强化【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm本篇技术指南围绕 drizzle-orm 0.44.5 发布说明changelogs/drizzle-orm/0.44.5.md中的四项修复展开深入讲解 Durable Objects SQLite 驱动下.one()查询方法的正确用法以及 SQLiteblob列在 Node.js、浏览器等不同运行时下的取值映射机制。读完本文你将理解这四条修复背后的底层实现掌握blob列三种模式buffer/json/bigint的选型原则并能安全升级到该版本。版本概览一次聚焦于 SQLite 稳定性与兼容性的小版本drizzle-orm 0.44.5 是紧随 0.44.4该版本修复了DrizzleQueryError导出问题见 changelogs/drizzle-orm/0.44.4.md之后的一个补丁级版本共包含四项变更全部集中在 SQLite 相关能力上修复durable-sqlitesession 中.one()的无效用法invalid usage修复 SQLiteblob列在 spread展开运算符场景下的崩溃问题提升 SQLiteblob列在浏览器环境中的支持改进 SQLiteblob列的值映射mapping逻辑。四项变更中三项都围绕blob列可见该版本的核心主题是让blob列在不同运行时与不同输入形态下都能稳定工作同时兼顾了 Cloudflare Durable Objects 上 SQLite 查询体验的一致性。durable-sqlite session 的.one()修复理解 execute 方法分发机制修复背景.one()与 SQLite execute 方法的对应关系在 drizzle-orm 的查询构建体系中SQLite 的预编译查询支持四种执行方法定义在 drizzle-orm/src/sqlite-core/session.tsexport type SQLiteExecuteMethod run | all | get;而SQLitePreparedQuery基类的execute()会根据executeMethod动态分发到对应实现见 sqlite-core/session.tsexecute(placeholderValues?: Recordstring, unknown): ExecuteResultT[type], T[execute] { return thisthis.executeMethod as ExecuteResultT[type], T[execute]; }查询构建器上的.one()方法约定语义为恰好返回一条记录在底层会映射为executeMethod get最终调用预编译查询对象的get()方法。因此session 的get()实现是否正确、是否符合基类契约直接决定了.one()能否正常工作。修复内容SQLiteDOPreparedQuery.get()的取值方式在 drizzle-orm/src/durable-sqlite/session.ts 中SQLiteDOPreparedQuery的get()实现如下get(placeholderValues?: Recordstring, unknown): T[get] { const params fillPlaceholders(this.query.params, placeholderValues ?? {}); this.logger.logQuery(this.query.sql, params); const { fields, client, joinsNotNullableMap, customResultMapper, query } this; if (!fields !customResultMapper) { return (params.length 0 ? client.sql.exec(query.sql, ...params) : client.sql.exec(query.sql)).next().value; } const rows this.values(placeholderValues) as unknown[][]; const row rows[0]; if (!row) { return undefined; } if (customResultMapper) { return customResultMapper(rows) as T[get]; } return mapResultRow(fields!, row, joinsNotNullableMap); }该实现遵循了 SQLite 同步驱动sync类型的取值契约无字段映射时直接通过client.sql.exec(...)执行 SQL并取结果集的next().value作为单行有字段映射如带fields的联表查询或自定义结果映射器时则走values()拿到原始行数组再取首行。旧版本中.one()在此 session 下无法正常工作很可能与get()对无字段/有字段两种路径的处理不完整有关0.44.5 将其修正为与 durable-sqlite/driver.ts 中drizzle()入口所创建的SQLiteDOSession见 durable-sqlite/session.ts一致的完整语义。实际影响与验证方式修复后在 Cloudflare Durable Objects 中使用 SQLite通过DurableObjectStorage的sqlAPI时db.select().from(table).where(...).one()这类查询将稳定返回单条记录无匹配时返回undefined。从源码结构看SQLiteDOPreparedQuery的run()session.ts、all()session.ts、values()session.ts分别对应写操作、多行查询与原始值数组查询三者此前不受影响本次修复补齐的是.one()这条单行取值链路。修复 spread 运算符导致的 blob 崩溃输入形态归一化问题本质驱动返回的二进制对象形态不一SQLite 的blob列在各驱动与运行时下读回的值可能是Buffer、Uint8Array或ArrayBuffer中的任意一种。若列映射代码以展开spread方式处理这些二进制对象例如对Uint8Array执行Buffer.from(...value)或对类数组结构做展开在不同形态之间切换时就会触发运行时崩溃——这正是 0.44.5 修复的第二项问题。修复方式在mapFromDriverValue中统一转换为 Buffer查看 drizzle-orm/src/sqlite-core/columns/blob.ts默认buffer模式的取值映射已经改为基于类型判断的安全转换override mapFromDriverValue(value: Buffer | Uint8Array | ArrayBuffer): T[data] { if (Buffer.isBuffer(value)) { return value; } return Buffer.from(value as Uint8Array); }不再对二进制对象做逐元素展开而是直接通过Buffer.from()整体拷贝从根源上消除了 spread 运算符在二进制对象上可能引发的崩溃。从代码结构可以推断此前版本可能对Uint8Array/ArrayBuffer使用了展开或逐个元素拷贝的写法遇到非 Buffer 输入时就会出错现在所有输入都被归一化为Buffer后续逻辑只依赖一种稳定形态。浏览器环境下的 blob 支持textDecoder兜底路径问题背景浏览器没有全局 BufferSQLite 的blob映射逻辑尤其是json与bigint两种需要把字节解码为文本的模式在 Node.js 中依赖全局Buffer。但在浏览器如 D1 HTTP 调用、libsql wasm、浏览器内运行的 SQLite 场景中全局Buffer并不存在直接调用Buffer.from(...)会抛错。0.44.5 的Better browser support即针对此问题。源码实现环境探测 双路径解码以json模式SQLiteBlobJson的取值为例blob.ts 的实现为override mapFromDriverValue(value: Buffer | Uint8Array | ArrayBuffer): T[data] { if (typeof Buffer ! undefined Buffer.from) { const buf Buffer.isBuffer(value) ? value // eslint-disable-next-line no-instanceof/no-instanceof : value instanceof ArrayBuffer ? Buffer.from(value) : value.buffer ? Buffer.from(value.buffer, value.byteOffset, value.byteLength) : Buffer.from(value); return JSON.parse(buf.toString(utf8)); } return JSON.parse(textDecoder!.decode(value)); }关键点有三环境探测先判断typeof Buffer ! undefined Buffer.from存在才走 Node 路径形态归一Node 路径下再区分Buffer、ArrayBuffer、带buffer视图的Uint8Array注意通过byteOffset/byteLength精确切分子视图最终统一为Buffer兜底解码浏览器环境回退到textDecoder.decode(value)——该textDecoder从 drizzle-orm/src/utils.ts 引入textDecoder常量见 blob.ts 第 5 行的导入同样是bigint模式SQLiteBigIntblob.ts的兜底方案。这一先探测、再归一、终兜底的三层结构正是该版本把 blob 支持扩展到浏览器运行时的实现基础。blob 映射的全面改进三种模式选型指南blob()工厂函数与三种模式blob()是 SQLite 列构造器定义于 drizzle-orm/src/sqlite-core/columns/blob.ts根据配置返回不同的列类型export function blob(): SQLiteBlobJsonBuilderInitial; export function blobTMode extends BlobMode BlobMode( config?: BlobConfigTMode, ): EqualTMode, bigint extends true ? SQLiteBigIntBuilderInitial : EqualTMode, buffer extends true ? SQLiteBlobBufferBuilderInitial : SQLiteBlobJsonBuilderInitial; // ... 带列名的重载 ... export function blob(a?: string | BlobConfig, b?: BlobConfig) { const { name, config } getColumnNameAndConfigBlobConfig | undefined(a, b); if (config?.mode json) { return new SQLiteBlobJsonBuilder(name); } if (config?.mode bigint) { return new SQLiteBigIntBuilder(name); } return new SQLiteBlobBufferBuilder(name); }三种模式BlobMode见 blob.ts对比如下模式列类型TypeScript 数据类型驱动参数类型写入映射读取映射buffer默认SQLiteBlobBufferBufferBuffer原样传递Buffer.isBuffer(value) ? value : Buffer.from(value)jsonSQLiteBlobJsonunknownJSON 值BufferBuffer.from(JSON.stringify(value))JSON.parse(buf.toString(utf8))bigintSQLiteBigIntbigintBufferBuffer.from(value.toString())BigInt(buf.toString(utf8))使用建议默认不传mode时得到buffer模式适合存储原始二进制数据文件内容、哈希值等需要把对象/数组以 JSON 形式存入 blob 时使用blob(data, { mode: json })。不过官方在 blob.ts 的注释中明确提示推荐优先使用text(..., { mode: json })替代 JSON 模式的 blob因为 SQLite 的 JSON 函数会对 BLOB 参数抛错BLOB 被保留用于未来 JSON 的二进制编码见 SQLite json1 文档说明需要把bigint存入 blobSQLite 本身无原生 bigint 类型时使用blob(id, { mode: bigint })写入时按 UTF-8 编码数字字符串读取时通过BigInt()还原。本次映射改进的要点0.44.5 对映射逻辑的改进主要体现在输入归一化与视图精确处理两点所有模式的mapFromDriverValue都接受Buffer | Uint8Array | ArrayBuffer三种输入对于Uint8Array子视图value.buffer存在且偏移非零的情况通过Buffer.from(value.buffer, value.byteOffset, value.byteLength)精确拷贝避免因偏移量导致数据错位。这些改动共同保证了不同驱动、不同运行时下 blob 读写结果的一致性。升级建议与验证路径0.44.5 是纯修复性质的补丁版本不包含破坏性变更可以放心升级若你使用了 durable-sqlite 驱动Cloudflare Durable Objects 上的 SQLite升级后重点回归select ... .one()单行查询路径确认返回单条记录或undefined且不再报错若你使用了 blob 列升级后请在目标运行时Node.js 或浏览器环境分别执行读写冒烟测试覆盖三种模式buffer/json/bigint并特别验证Uint8Array子视图数据如bytes.subarray(...)的读取结果与 JSON/bigint 文本解码是否正确相关实现均可直接查阅源码继续深入durable-sqlite 会话与查询在 drizzle-orm/src/durable-sqlite/session.ts入口在 drizzle-orm/src/durable-sqlite/driver.tsblob 列三种模式的完整实现与文档注释在 drizzle-orm/src/sqlite-core/columns/blob.ts。结语drizzle-orm 0.44.5 是一个典型的小版本大修内功的补丁修复了 durable-sqlite 上.one()查询的可用性问题并为 SQLiteblob列建立了环境探测 → 输入归一 → 文本兜底的三层取值管线使其在 Node 与浏览器环境下都能稳定映射buffer/json/bigint三种模式。对于在 Cloudflare Durable Objects、浏览器端 SQLite 场景中使用 drizzle-orm 的开发者这是一个值得关注的稳定性更新。【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考