Repository navigation
msnodesqlv8 v6: support drivers that hold back a paused query's events #1940
Description
Background
On 2026-10-17, msnodesqlv8 merged groundwork for its next major version (TimelordUK/node-sqlserver-v8#482, #484, #485, #486). It is not released yet. Upstream master's package.json still says 5.6.0, and its engines asks for Node 22 or later. These are the changes that matter to us:
- A paused query emits nothing until it is resumed. That includes
meta,doneandfree, and what a native call already in flight brings back. resume()only runs the step that is waiting. It no longer fetches whileSQLExecDirectorSQLMoreResultsis still running.- Cancelling a paused query ends it with
HY008, thenfree. The statement is no longer freed while a native call is in flight. - A paused query holds its connection. New work on that connection is refused with
HY010.
node-mssql declares no msnodesqlv8 version range, so users can install v6 as soon as it is published.
What we found
We built upstream master (aa57e17) from source and ran it on Windows CI against SQL Server 2022, with 5.6.0 alongside for comparison.
msnodesqlv8 on its own:
| 5.6.0 | master | |
|---|---|---|
| Paused query cancelled after a flushed row count (the crash #1938 works around) | segfault in 6 of 6 runs | no crash in 6 runs |
| Paused query resumed while it executes (#1924, which #1928 fixes) | extra HY010 on every failing query |
fixed |
node-mssql's msnodesqlv8 suite and scenarios on master:
| Adapter | Result |
|---|---|
| node-mssql master | Full suite passes (158). Every cancel and resume scenario is correct. |
| #1938 | Cancelling a stream held before its first result set hangs. The deferred cancel waits for meta, done or free, and v6 never emits them while the query is paused. |
| #1938 with #1928 on top | Also hangs on any stream resumed while it is held, because the resume waits for meta. 4 tests time out, including streaming resume. |
So both workarounds are right for 5.6.0 and earlier, where the bugs are. Under v6 they must be switched off.
Decision
Wait for the upstream release before choosing how to tell the two apart. Until then a version check can't, because master is still versioned 5.6.0. Master can be told apart by internals, such as DriverMgr.prototype.pausedQuery and Query.prototype.cancelPaused.
Tasks
- Once v6 is released, decide how to detect it, by major version, a behaviour marker, or both. Switch off fix: stop msnodesqlv8 crashing when a stream held before its first result set is cancelled #1938's deferred cancel and fix: stop msnodesqlv8 streams failing when resumed while their query executes #1928's held resume when it is present.
- Add a Windows CI job against the v6 release. Until then it could run against upstream master as a job that isn't required to pass.
- Treat an
HY010refusal ("query on this connection is paused") as a connection error, so the pool drops the connection. - Docs: say that msnodesqlv8 6 needs Node 22 or later.
- Keep the handling for 5.6.0: a failed statement's info messages are emitted before its error (3621 "The statement has been terminated." arrives before 2627) TimelordUK/node-sqlserver-v8#478 and Fix README issues #479 until upstream ships those fixes: no
doneafter an error that ends the batch, the droppedHY008, and thefreefallback. - Once v6 is the oldest supported version, remove the 5.x-only paths added by fix: stop msnodesqlv8 streams losing rows under back pressure #1919, fix: stop msnodesqlv8 streams failing when resumed while their query executes #1928 and fix: stop msnodesqlv8 crashing when a stream held before its first result set is cancelled #1938.
- Investigate, found by code reading only: on Linux with ODBC Driver 17, msnodesqlv8's JS query timeout frees the statement while the execute may still be running. This affects 5.6.0 and master, and ODBC Driver 17 is node-mssql's default on Linux.
Related: #1924, #1928, #1938, TimelordUK/node-sqlserver-v8#478, #479, #480, #481.
Activity