ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Drizzle ORM 0.28.2 版本解析:社区贡献合入、MySQL 时间戳毫秒截断修复与 Typebox 支持

Drizzle ORM 0.28.2 版本解析:社区贡献合入、MySQL 时间戳毫秒截断修复与 Typebox 支持 Drizzle ORM 0.28.2 版本解析社区贡献合入、MySQL 时间戳毫秒截断修复与 Typebox 支持【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-ormDrizzle ORM 0.28.2 是 0.28.0 大版本发布后的第二个补丁版本以社区贡献为主体合入了 D1 驱动测试集、内部文档修订并修复了 MySQL 时间戳毫秒被截断、SQLite 方言get()返回类型错误以及 sqlite-proxy 查询执行两次等三个影响实际使用的 Bug同时宣布了面向 JSON Schema 生态的drizzle-typebox新包。本文以 changelogs/drizzle-orm/0.28.2.md 为主干结合仓库源码逐项还原这些变更背后的实现细节帮助读者理解升级到 0.28.x 后应该注意的行为差异与修复原理。版本背景0.28.x 系列上下文0.28.2 属于 Drizzle ORM 0.28.0 发布后的稳定化补丁序列。0.28.0 引入了破坏性变更移除了关系查询where回调中访问with/extras字段的能力、关系查询全新的 lateral join 生成策略以及mysql2驱动的mode: planetscale配置0.28.1 则修复了 0.28.0 引入的 PostgreSQL 数组相关问题。到了 0.28.2变更重点转向社区合入的质量加固与驱动级细节修复没有新的破坏性变更因此已处于 0.28.x 的升级是平滑的。新增 D1 测试集Cloudflare D1 驱动的可靠性加固变更内容0.28.2 由社区开发者 AdiRishi 为 D1 驱动补充了一组测试。D1 是 Cloudflare Workers 平台提供的 SQLite 兼容数据库服务Drizzle 通过 drizzle-orm/src/d1/driver.ts 与 drizzle-orm/src/d1/session.ts 为其提供支持。实现背景从源码结构看DrizzleD1Database继承自BaseSQLiteDatabaseasync, D1Result, TSchema并扩展了batch()批量执行能力见 driver.ts。由于 D1 与本地 SQLite 在驱动 API、会话缓存config.cache、批量事务语义上存在差异此前该驱动缺少覆盖性测试。0.28.2 合入的测试集为 D1 的查询执行、会话管理路径提供了回归保护降低了后续版本在异步方言与缓存机制上引入回归的风险。升级含义对使用drizzle-orm/d1的 Cloudflare Workers 项目此变更不改变任何 API 或运行时行为属于纯测试质量改进但它意味着 0.28.2 之后 D1 相关行为有更强的回归保障值得在升级时一并回归验证你的 D1 查询与batch调用。内部文档修订面向贡献者的工程清理balazsorban44 与 pyk 修复了仓库内部文档中的若干问题。这类变更属于工程维护性工作不影响运行时行为但降低了贡献者理解代码结构与构建流程的门槛。仓库中的相关文档包括 CONTRIBUTING.md、README.md 以及各子包如 drizzle-typebox/README.md的说明。Bug 修复一MySQL 时间戳毫秒截断问题问题表现MySQL 的timestamp/datetime类型在指定fspfractional seconds precision小数秒精度时可以存储毫秒但 0.28.2 之前的序列化逻辑在将 JSDate写入数据库时存在毫秒截断。源码定位与修复原理MySQL 时间戳列的驱动参数映射集中在 drizzle-orm/src/mysql-core/columns/timestamp.ts 与 drizzle-orm/src/mysql-core/columns/datetime.ts。修复前的时间戳写入路径// timestamp.ts 中的 mapToDriverValue return value.toISOString().slice(0, -1).replace(T, );toISOString()输出的格式为2026-09-18T05:58:28.123Z其中毫秒段是123。slice(0, -1)去掉末尾的Z后替换T得到2026-09-18 05:58:28.123。毫秒本应保留但在旧版本实现中序列化过程可能在后续环节截断了小数部分导致2026-09-18 05:58:28.123被写入为2026-09-18 05:58:28造成毫秒精度丢失。0.28.2 修复了该路径使带fsp的时间戳列能完整保留毫秒。同时datetime列的映射实现见 datetime.ts// 写入Date - YYYY-MM-DD HH:mm:ss.SSS return value.toISOString().replace(T, ).replace(Z, ); // 读取YYYY-MM-DD HH:mm:ss.SSS - Date return new Date(value.replace( , T) Z);使用建议在 Drizzle 中创建带毫秒精度的 MySQL 时间戳列通过fsp配置声明小数秒精度import { mysqlTable, timestamp } from drizzle-orm/mysql-core; export const events mysqlTable(events, { createdAt: timestamp(created_at, { mode: date, fsp: 3 }), });fsp取值范围为 0–6对应 TimestampFsp 类型fsp: 3即毫秒精度。升级到 0.28.2 后写入该列的Date的毫秒部分将完整保留读取时同样能还原毫秒需要比对前后写入值以验证修复效果。Bug 修复二SQLite 方言get()方法返回类型修正问题表现Issue #565 反映 SQLite 系方言的get()方法返回类型不正确导致类型层面的使用错误。该 issue 已在 0.28.2 关闭。修复内容0.28.2 由 stefanmaric 修正了基于 SQLite 方言的get()方法类型签名使其与实际返回的查询结果类型一致。SQLite 系列驱动better-sqlite3、bun-sqlite、d1、libsql 等对应 drizzle-orm/src/better-sqlite3、drizzle-orm/src/d1 等目录在升级后调用db.select(...).get()得到的类型推断将更准确无需再手动断言。类型层验证此修复属于类型声明层面的调整可从 drizzle-orm/type-tests/sqlite 的类型测试集了解 SQLite 方言类型断言的覆盖范围。升级后若在get()返回值上出现类型报错请以运行期真实返回为准检查旧类型断言是否已不再需要。Bug 修复三sqlite-proxy 查询执行两次问题表现0.28.2 修复了 sqlite-proxy 驱动中查询被执行两次的缺陷由 mosch 修复。该 Bug 会让一次 API 调用在远程代理端触发两次 SQL 执行造成双倍请求开销与潜在的副作用重复。原理分析从 drizzle-orm/src/sqlite-proxy/session.ts 的会话实现看sqlite-proxy 通过回调函数把查询透传给远端处理执行路径中若存在重复调用或对同一查询句柄的多次run/all/get触发就会导致代理端收到两条相同 SQL。修复的核心是确保一条查询语句只触发一次代理回调。验证方式使用drizzle-orm/sqlite-proxy的项目可在代理回调中打印接收到的 SQL 日志对比升级前后单次调用对应的执行次数应观察到由 2 次降为 1 次。若你在代理端做过请求计数或副作用操作此修复能避免重复执行带来的数据重复写入。新包发布drizzle-typebox 提供 Typebox 支持变更内容0.28.2 同期发布了新的 drizzle-typebox 包贡献者 Bulbang允许直接从 Drizzle 表/视图定义生成 Typebox JSON Schema。这使同一套表结构定义既能驱动 ORM 查询又能为运行时校验框架如 Fastify、Ajv 校验链路提供 Schema。包结构与核心 API仓库中的 drizzle-typebox/src 目录结构如下schema.ts核心入口提供createSelectSchema、createInsertSchema、createUpdateSchema与createSchemaFactorycolumn.ts列到 Typebox Schema 的映射逻辑columnToSchema以及bufferSchema、jsonSchema、literalSchema导出column.types.ts、schema.types.ts类型层定义保证生成的 Schema 类型精确schema.types.internal.ts内部类型工具utils.tsisColumnType、isWithEnum等类型守卫constants.ts各整数类型的边界常量包对外导出来源于 index.tsexport { bufferSchema, jsonSchema, literalSchema } from ./column.ts; export * from ./column.types.ts; export * from ./schema.ts; export * from ./schema.types.internal.ts; export * from ./schema.types.ts; export * from ./utils.ts;基本用法import { createInsertSchema, createSelectSchema, createUpdateSchema } from drizzle-typebox; import { pgTable, serial, text, timestamp } from drizzle-orm/pg-core; const users pgTable(users, { id: serial(id).primaryKey(), name: text(name).notNull(), email: text(email), createdAt: timestamp(created_at).defaultNow(), }); // 三种场景的 JSON Schema const selectUserSchema createSelectSchema(users); const insertUserSchema createInsertSchema(users); const updateUserSchema createUpdateSchema(users);三种 Schema 的空值/可选性语义从 schema.ts 的Conditions定义可以看出三种 Schema 的差异这是源码级可验证的核心行为Schema 类型never被排除optional可选nullable可空createSelectSchema永不排除永不可选!column.notNullcreateInsertSchemagenerated.type always或generatedIdentity.type always的列!notNull或notNull hasDefault!column.notNullcreateUpdateSchema同 insert生成列排除所有列可选!column.notNull即createSelectSchema会把非空列生成为必填、可空列生成为T | nullcreateInsertSchema对有默认值的非空列也标记为可选optional在 handleColumns 中通过t.Optional实现createUpdateSchema默认所有列均可选适合只更新部分字段的场景。生成列如自增主键在 insert/update 中被自动剔除。自定义 refinement 与条件控制create*Schema均支持第二个参数refine可以对特定列做 Schema 覆写或链式加工import { Type as t } from sinclair/typebox; const insertUserSchema createInsertSchema(users, { name: (schema) t.String({ ...schema, minLength: 3, maxLength: 50 }), email: t.String({ format: email }), // 直接替换整列 Schema });从 handleColumns 的实现可见当 refinement 是普通对象时直接作为该列的 Schema当它是函数时会以自动映射出的 Schema 为参数调用返回加工后的 Schema。列类型到 Typebox Schema 的映射细节columnToSchema 按列类型逐类映射关键映射如下枚举列t.Enum(mapEnumValues(enumValues))将数据库枚举映射为 Typebox 枚举数字列按列类型映射到对应整数范围如MySqlTinyInt映射到INT8_MIN/MAXPgBigInt53/SQLiteInteger映射到Number.MIN_SAFE_INTEGER~Number.MAX_SAFE_INTEGER范围常量见 constants.ts并使用minimum/maximum约束bigint 列t.BigInt并带INT64边界字符串列PgUUID映射为format: uuidPgVarchar/SQLiteText带maxLength: column.lengthPgChar/MySqlChar固定长度minLength maxLengthPostgres 专用类型PgVector/PgHalfVector映射为定长/变长number[]PgPoint/PgGeometry映射为[number, number]元组或{x, y}对象PgLine映射为三元组或{a,b,c}PgArrayt.Array(columnToSchema(baseColumn))且column.size存在时限定minItems/maxItemsjsonjsonSchema联合了字面量、数组与对象buffer自定义bufferSchema{ [Kind]: Buffer, type: buffer }并注册了对应的TypeRegistry未知/自定义类型回退到t.Any()自定义 Typebox 实例createSchemaFactory若项目中使用了自定义的 Typebox 实例例如安装了不同版本的sinclair/typebox或配置了自定义格式可通过createSchemaFactory注入import { createSchemaFactory } from drizzle-typebox; import { Type } from sinclair/typebox; const { createSelectSchema, createInsertSchema, createUpdateSchema } createSchemaFactory({ typeboxInstance: Type }); const selectUserSchema createSelectSchema(users);该工厂接受CreateSchemaFactoryOptions见 schema.types.ts其typeboxInstance会贯穿handleEnum、handleColumns等所有生成路径见 schema.ts。与已有 drizzle-zod / drizzle-valibot / drizzle-arktype 生态的关系仓库中已存在同构的 drizzle-zod、drizzle-valibot、drizzle-arktype 包drizzle-typebox 遵循完全一致的设计模式同为column.ts schema.ts schema.types.ts结构。选择哪个取决于项目使用的运行时校验库Typebox 常与 Fastify、Ajv 配合Zod 生态成熟Valibot 更轻量ArkType 侧重类型推断。它们都基于 Drizzle 列元数据自动推导 Schema避免手写重复的类型与校验定义。测试覆盖drizzle-typebox 的测试位于 drizzle-typebox/tests覆盖pg.test.ts、mysql.test.ts、sqlite.test.ts、singlestore.test.ts四种方言可从测试用例中查看各数据库类型映射的预期输出例如tests/pg.test.ts中针对 Postgres 枚举、vector、几何类型的断言。升级建议与总结升级路径0.28.2 无破坏性变更从 0.28.0/0.28.1 可直接升级从更早版本升级需先阅读 0.28.0 变更日志确认关系查询where回调破坏性变更与mysql2的mode配置是否影响你的代码。受影响面MySQL 时间戳毫秒精度尤其使用fsp列的应用、SQLite 系列get()类型推断、sqlite-proxy 双执行问题。新能力需要 Typebox JSON Schema 的项目可引入drizzle-typebox与既有 drizzle-zod 等包按需并存。回归验证升级后建议对 D1 批量操作、MySQL 毫秒级时间戳读写、sqlite-proxy 请求日志进行一轮针对性验证。0.28.2 证明了补丁版本同样可以承载实质价值三个 Bug 修复分别落在驱动映射精度MySQL 时间戳、类型系统正确性SQLiteget()与执行路径幂等性sqlite-proxy三个层面而 drizzle-typebox 的加入则让 Drizzle 的类型安全能力进一步延伸到运行时校验领域。【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表