fix(db): bind every raw-sql Date through its column encoder (#6337)

* fix(db): bind every raw-sql Date through its column encoder

`drizzle()` overwrites postgres-js's temporal serializers (OIDs 1082/1083/
1114/1184/1182/1185/1115/1231) with an identity function because drizzle maps
timestamps itself through the column's `mapToDriverValue`. A raw `sql` template
carries no column context, so an interpolated `Date` skips that mapping, reaches
the identity serializer unchanged, and the wire encoder throws
`ERR_INVALID_ARG_TYPE`. The pools' `prepare` / `fetch_types` options are
irrelevant: the serializer swap happens for all four combinations.

Five live sites still interpolated a bare `Date`, the stale schedule-job filter
among them — it has no try/catch, so a database async backend would surface a
500 from the schedule tick. Bind each cutoff with `sql.param(date, column)`.

The testing `sql` mock's guard cannot see untested code or the tests that
override the drizzle-orm mock, so add `check:sql-date-binding`: a Babel-AST
audit over apps/** and packages/** that resolves Date-valued bindings per file
and rejects any that reach a raw template unbound. Correct the mock's comment,
which attributed the failure to postgres-js under `fetch_types: false`.

* fix(scripts): require the documented sql-date-bound annotation form and a reason
This commit is contained in:
Waleed
2026-08-06 12:16:27 -07:00
committed by GitHub
parent 8e3e608c53
commit 2ba455647b
13 changed files with 442 additions and 23 deletions
+3
View File
@@ -159,6 +159,9 @@ jobs:
- name: Tool request transport boundary audit
run: bun run check:tool-request-boundary
- name: SQL Date binding audit
run: bun run check:sql-date-binding
- name: Verify generated tool metadata is in sync
run: bun run tool-metadata:check