数据库
实现或修改 Prisma 7 SQL 驱动适配器时的事务…
在实现或修改 Prisma ORM 7 的 SQL driver adapter(含 SqlDriverAdapter、Transaction、savepoint、结果映射、DriverAdapterError)时,提供可执行的事务生命周期、类型映射与错误保留做法。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
实现或修改 Prisma 7 SQL 驱特定
解决思路
- 使用目标 Prisma 版本实际安装的 @prisma/driver-adapter-utils 版本作为参考,因为 driver adapter 是协议边界,类型兼容的代码仍可能破坏值、泄漏连接或破坏事务。
- 实现 SqlDriverAdapterFactory、SqlMigrationAwareDriverAdapterFactory、SqlDriverAdapter 或 Transaction 时,遵循契约快照中的接口定义。
- IsolationLevel 目前包括 READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SNAPSHOT 和 SERIALIZABLE;需验证具体数据库支持哪些级别。
- 每个事务使用一个专用连接,防止交错和连接泄漏。
- commit/rollback 仅作为生命周期清理钩子,不要重复发出 SQL COMMIT/ROLLBACK。
- Savepoint 放在 Transaction 上,而不是适配器全局深度,使嵌套作用域是连接本地的。
- 保留原始数据库错误码和消息,以便 Prisma 在未映射错误时回退到有用的 P2039。
- 精确映射参数和结果元数据,防止值被静默破坏。
- 影子数据库必须隔离并始终清理,确保 Migrate 安全。
- 只释放适配器自己拥有的资源,避免关闭调用方拥有的连接池。
- queryRaw 中根据 SqlQuery 的 sql、args 和并行的 argTypes,对每个参数同时使用值和 ArgType 进行映射,不要丢弃类型/参数个数信息。
- 以驱动的数组/元组行模式执行查询,保证列顺序稳定。
- queryRaw 返回的 columnNames、columnTypes 和 rows 必须长度和顺序一致。
- 将驱动元数据有意识地映射到 ColumnTypeEnum:有符号整数宽度映射到 Int32/Int64,64 位值不要被 JS number 截断。
- decimal/numeric 映射到 Numeric,并使用 Prisma 期望的表示形式。
- binary 映射到 Uint8Array/Bytes。
- date-only、time-only 和 timestamp 分别映射到 Date、Time 和 DateTime。
- UUID、JSON、enum、数组以及提供方特定的未知值映射到其显式类型。
- 不支持的原生类型映射为 DriverAdapterError({ kind: 'UnsupportedNativeDataType', type })。
- 测试 null、空数组、数组元素类型、大整数、decimal、字节数组、JSON、日期以及用户定义/未知原生类型。
- executeScript 必须按提供方期望的方式执行迁移脚本;优先使用驱动原生多语句/脚本能力或真正的 SQL 解析器,不要简单按分号拆分,否则会破坏函数、触发器、引号字符串和方言特定块。
- startTransaction 必须获取一个专用连接、启动数据库事务、应用请求的隔离级别,并返回绑定到同一连接的 Transaction;如果设置失败,立即释放连接。
- 在 startTransaction 中,先获取连接,创建事务对象并传入释放回调,执行 BEGIN,若指定隔离级别则执行 SET TRANSACTION ISOLATION LEVEL(使用 validateLevel 校验),失败时释放连接并抛出适配器错误。
- Transaction 的 commit() 和 rollback() 是生命周期钩子:分离监听器并只释放一次专用连接,不得发出第二次 SQL commit/rollback。
- 实现可选的 savepoint 方法(createSavepoint、rollbackToSavepoint、releaseSavepoint)时,仅在提供方支持的地方实现,并校验/引用 savepoint 标识符。
- 对于 savepoint 故意为 no-op 的提供方,记录并测试该限制。
- 绝不要在共享适配器上保存事务深度;并行事务会使适配器全局深度不正确,嵌套状态应属于返回的事务连接和 Prisma 的 savepoint 调用。
- 将可识别的驱动失败包装为 DriverAdapterError,并把已知条件映射到 MappedError 类型,如约束违反、认证/可达性、表/列/数据库缺失、超时、已关闭事务、无效输入、值范围和写冲突。
- 对于数据库错误,即使回退到提供方特定的 raw 变体,也要保留 originalCode 和 originalMessage。
- 在 convertDriverError 中返回 originalCode、originalMessage 以及 mapKnownOrRaw 的结果。
- 在 mapKnownOrRaw 中,对已知错误码返回结构化 MappedError(如 23505 返回 UniqueConstraintViolation),否则返回提供方特定 raw 变体并保留 code、severity、message、detail、column、hint。
- throwAdapterError 中,仅对数据库错误抛出 DriverAdapterError;真正意外的非驱动错误应重新抛出,让编程 bug 保持可见,不要用伪造的 GenericJs id 替换所有未知异常。
- connect() 返回一个新的可用适配器连接/连接池包装。
- 跟踪工厂是否创建了连接池;dispose() 关闭自己拥有的连接池,对调用方拥有的连接池只分离监听器,除非显式选项转移所有权。
- 仅当 connectToShadowDb() 能创建隔离的影子数据库、连接它并在 dispose/失败清理时删除它时,才实现 SqlMigrationAwareDriverAdapterFactory。
- 绝不要让影子适配器指向主数据库;引用生成的标识符并使用加密唯一名称。
- getConnectionInfo() 应准确报告 schemaName、适用时的 maxBindValues 以及 supportsRelationJoins。
- 验证清单:针对确切目标 @prisma/driver-adapter-utils 版本做类型检查。
- 验证清单:queryRaw 保留列顺序、类型、null 和精度。
- 验证清单:executeRaw 正确报告受影响行数。
- 验证清单:executeScript 处理提供方特定的多语句语法。
- 验证清单:并发交互式事务使用不同的专用连接。
- 验证清单:成功时提交并释放一次;失败时回滚并释放一次。
- 验证清单:嵌套事务测试覆盖 create/rollback/release savepoint 钩子。
- 验证清单:不支持的隔离级别以 InvalidIsolationLevel 失败。
- 验证清单:已知约束映射为结构化错误。
- 验证清单:未映射的数据库错误保留原始 code/message 并产生有用的 P2039。
- 验证清单:针对内部和外部连接池测试 dispose 所有权。
- 验证清单:影子数据库的创建、使用、失败清理和释放都是隔离的。
- 验证清单:运行 Prisma Client 集成/E2E 测试,而不仅是适配器单元测试。
适用边界 · 注意事项
- 不适用于非 Prisma ORM 7 或非 SQL driver adapter 的工作。
- 不适用于没有安装对应版本 @prisma/driver-adapter-utils 的环境。
- 不适用于不需要事务、savepoint、结果映射或 DriverAdapterError 行为的普通数据库查询封装。