feat(drizzle): tag queries issued inside transactions#18
Merged
Conversation
`patchDrizzle` patched the top-level db, but `db.transaction(cb)` hands `cb` a fresh `tx` object whose query methods were never patched — so every query built inside a transaction lost its `file`/`func_name` tags. Only `db_driver` (added in the session-level `prepareQuery` patch) survived, which is why transaction writes showed up in Query Doctor with no source provenance. Wrap `transaction` (recursively, for nested savepoint transactions) so the `tx` handed to the callback gets the same per-query caller capture. `file` is now always present inside a transaction; `func_name` resolves when the callback (or its enclosing function) is named — anonymous `async (tx) => …` arrows still get `file` alone, as expected. Verified against pglite: all query types, nested savepoints, concurrency, and — crucially — commit/rollback semantics are preserved (the wrapper only augments the callback, it doesn't change transaction control flow). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Transaction query tagging. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a gap surfaced while dogfooding on d2armory: queries issued inside
db.transaction(...)had no source provenance — Query Doctor showed them with onlydb_driver, nofile/func_name.Root cause (verified, not assumed)
patchDrizzlepatches the query methods on the top-level db. Butdb.transaction(cb)handscba freshtxobject whoseselect/insert/update/delete/executewere never patched, socurrentCalleris never set for those queries.db_driverstill appears because it's added in the session-levelprepareQuerypatch (shared prototype), but the caller-derived tags are dropped.Reproduced on pglite:
Fix
Wrap
transactionso thetxhanded to the callback is patched the same way — recursively, so nested savepoint transactions are covered too. The wrapper only augments the callback; it doesn't touch transaction control flow.fileis now always captured inside a transaction.func_nameresolves when the callback (or its enclosing function) is named; anonymousasync (tx) => …arrows still getfilealone (correct — there's no symbol).Verification
New
test/transaction.spec.ts(6 tests), all grounded in real behavior — and the 4 provenance tests fail on pre-fix code, pass on the fix:file; anonymous arrow → nofunc_name.func_name.Full suite: 32 pass (dual ESM/CJS build clean). Drizzle-only — mikroorm's
onQueryhook and typeorm'sQueryRunner.querypatch both already fire inside transactions.Version
drizzle 0.5.0 → 0.6.0 (new capability;
patchDrizzleAPI unchanged, so a drop-in bump for consumers).🤖 Generated with Claude Code