尧图精选

drizzle-orm 0.33.0 升级指南:postgres.js JSON 序列化破坏性变更与三类缺陷修复解析

🕒 发布时间:2026/9/19 4:37:19 📁 来源:尧图网络
drizzle-orm 0.33.0 升级指南postgres.js JSON 序列化破坏性变更与三类缺陷修复解析【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm本指南聚焦 drizzle-orm 0.33.0 版本的核心变更以 postgres.js 为驱动时 jsonb/json 字段的序列化行为被彻底调整破坏性变更以及 better-sqlite3 boolean 模式、isTable 助手、inArray/notInArray 文档等三个缺陷修复。读完本文你将理解该破坏性变更的底层原因、掌握存量数据的 SQL 迁移方案并了解新版类型判定与条件表达式 API 的正确用法。版本概要drizzle-orm 0.33.0 是 2024 年发布的常规版本主要包含1 项破坏性变更postgres.js 驱动的 JSON 类型处理方式仅影响部分 postgres.js 用户3 项缺陷修复better-sqlite3 预编译语句 boolean 模式、isTable助手函数、inArray/notInArray文档与实现。破坏性变更postgres.js 的 jsonb/json 字段不再被二次字符串化变更背景与根因在 0.33.0 之前如果你使用postgres-js驱动写入jsonb字段Drizzle 与 postgres.js 客户端之间可能存在双重序列化问题数据库中最终存下的是被字符串化的 JSON 字符串即外层又包了一层引号而不是真正的 JSON 对象/数组。用户侧表现是Drizzle 的insert、select操作看似正常因为 Drizzle 在读取时会尝试解析但直接查看数据库却发现字段是字符串形态。该问题在社区被反复报告对应缺陷编号为 #724jsonb 始终以 json 字符串插入与 #1511postgres 上 jsonb 类型实现不正确。从源码层面可以印证问题根源。0.33.0 修复的核心在于 postgres-js 驱动实现在构造 session 之前Drizzle 会通过transparentParser覆盖 postgres.js 默认的日期与 JSON 序列化器其中client.options.serializers[114] transparentParser; // json client.options.serializers[3802] transparentParser; // jsonb114是 PostgreSQL 中json类型的 OID3802是jsonb类型的 OID。将它们设置为“透传”序列化器后postgres.js 不再对 Drizzle 传入的值做额外的 JSON 字符串化处理。变更后的行为与处理其他驱动的方式一致0.33.0 将 PostgreSQL-JS 的行为调整为向驱动传入原始 JSON 值即与你在数据库中看到的形态保持一致。也就是说从 0.33.0 起写入你传给 Drizzle 的jsonb/json值对象或数组会以原始 JSON 值的形式交给 postgres.js 驱动落库不再被包成字符串读取查询结果中的jsonb/json值保持数据库中的原始形态。对于依赖旧行为数据库里存字符串的存量数据升级后需要一次性数据迁移对于新项目新旧行为下 Drizzle 的insert/select在 API 层面均可用但库内数据的物理形态发生了变化。官方在变更说明中也提示后续版本会继续以更复杂的方式统一 Drizzle 全局的驱动行为覆盖逻辑确保不覆盖驱动自身行为本次是先行修复 postgres.js。存量数据迁移将字符串字段还原为真实 JSON如果你的数据库中已经存在被字符串化的jsonb/json字段需要把它们从字符串转换为真正的 JSON 对象。变更说明给出了两条可直接执行的 SQL。使用 jsonb 时update table_name set jsonb_column (jsonb_column # {})::jsonb;使用 json 时update table_name set json_column (json_column # {})::json;# {}的作用是把 jsonb 值此处是外层字符串整体解包为文本再通过::jsonb/::json重新解析为 JSON 类型。官方说明该查询在多个场景下验证可用前提是所有被字符串化的对象都是对象或数组。包含基础类型值时的通用迁移方案如果字段中除对象/数组外还包含字符串、数字、布尔值等基础类型例如hello、123、true这类本身是字符串但内容是 JSON 字面量的情况直接整体转换可能会失败或改变语义此时应使用CASE条件分支仅当解包后的文本以{或[开头即 JSON 对象/数组时才转换其余保持原样。使用 jsonb 时UPDATE table_name SET jsonb_column CASE -- Convert to JSONB if it is a valid JSON object or array WHEN jsonb_column # {} LIKE {% OR jsonb_column # {} LIKE [% THEN (jsonb_column # {})::jsonb ELSE jsonb_column END WHERE jsonb_column IS NOT NULL;使用 json 时UPDATE table_name SET json_column CASE -- Convert to JSON if it is a valid JSON object or array WHEN json_column # {} LIKE {% OR json_column # {} LIKE [% THEN (json_column # {})::json ELSE json_column END WHERE json_column IS NOT NULL;建议在事务中执行迁移并在执行前备份相关表迁移完成后用一次SELECT抽查字段类型pg_typeof或驱动返回的 JS 类型确认已还原为对象/数组。源码级解析新行为下的序列化闭环新行为下列级序列化逻辑仍然由 Drizzle 的列类型负责。jsonb 列实现中override mapToDriverValue(value: T[data]): string { return JSON.stringify(value); } override mapFromDriverValue(value: T[data] | string): T[data] { if (typeof value string) { try { return JSON.parse(value); } catch { return value as T[data]; } } return value; }json列实现了相同的策略。可见 Drizzle 在“应用层”依旧完成JSON.stringify写入与JSON.parse读取的对称处理而 0.33.0 的关键变化是在“驱动层”取消了 postgres.js 对已序列化字符串的第二次包装从而避免JSON.stringify(JSON.stringify(obj))这种双重字符串化导致的脏数据。两层配合后insert与select在 Drizzle API 层面依然保持原有的对象语义用户代码通常无需改动只需处理存量数据。Bug 修复better-sqlite3 预编译语句下的 boolean 模式对应缺陷 #2568使用 better-sqlite3 时boolean模式的整数列在**预编译语句prepared statements**场景下工作不正常。在 SQLite 中没有原生布尔类型Drizzle 以整数列承载布尔语义。从 sqlite-core 的 integer 列定义可以看到其双向映射override mapFromDriverValue(value: number): boolean { return Number(value) 1; } override mapToDriverValue(value: boolean): number { return value ? 1 : 0; }即true ↔ 1、false ↔ 0。0.33.0 修复了该映射在预编译语句路径prepareQuery/PreparedQuery下未能正确生效的问题相关执行路径见 better-sqlite3 session 实现run/all/get/values等方法。升级后使用db.prepare(...)或通过条件构建器生成预编译查询时boolean 列的读写应与其他执行方式行为一致。isTable 助手函数对应缺陷 #2672isTable助手函数此前在部分场景下判断失效。isTable用于在运行时判断一个值是否为 Drizzle 的表定义Table其实现位于 table.tsexport function isTable(table: unknown): table is Table { return typeof table object table ! null IsDrizzleTable in table; }判定依据是对象上是否带有内部标记IsDrizzleTable该标记在 Table 类定义中被置为true。0.33.0 修复了该助手在特定构造路径下失效的问题。升级后可在类型守卫场景放心使用例如遍历 schema 对象筛选出表定义再执行批量操作import { isTable } from drizzle-orm; const tables Object.values(schema).filter((v) isTable(v));inArray / notInArray 文档与实现对应缺陷 #2690inArray与notInArray方法的官方文档存在过时之处。两者的实现位于 conditions.ts核心行为如下inArray(column, values)生成column in (...)条件当传入空数组时直接生成false条件不产生任何行notInArray(column, values)生成column not in (...)条件当传入空数组时直接生成true条件所有行均满足。典型用法// Select cars made by Ford or GM. db.select().from(cars) .where(inArray(cars.make, [Ford, GM])); // Select cars made by any company except Ford or GM. db.select().from(cars) .where(notInArray(cars.make, [Ford, GM]));值得注意的是空数组语义SQL 标准中IN ()在多数数据库里是非法语法而 Drizzle 选择将空数组安全地降级为常量布尔条件inArray空数组恒为falsenotInArray空数组恒为true这一行为既是实现细节也是文档需要准确描述的内容。0.33.0 同步修正了文档中对这一行为及相关签名的说明。升级建议确认驱动本次破坏性变更仅影响postgres-js驱动drizzle-orm/src/postgres-js 目录对应模块使用 node-postgres、Neon、pg-proxy 等其他 PG 驱动的用户不受影响。检查存量数据若长期使用 postgres.js 且写过 jsonb/json 字段先执行上述 SELECT 抽查字段物理形态再按对象/数组或混合场景选择对应的 UPDATE 迁移脚本。回归测试升级后针对 boolean 列better-sqlite3与isTable、inArray/notInArray三个修复点补充或运行回归用例确认行为与本文描述一致。升级配套工具若同时使用 drizzle-kit 生成迁移建议一并升级到与 0.33.0 匹配的版本避免 schema 差异比对与迁移 SQL 生成不一致。如果你在迁移过程中被存量数据问题阻塞可在社区中携带具体的表结构与数据样例反馈给维护者协助定位本文给出的 SQL 迁移方案已在官方发布的若干真实案例中验证通过。【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →