Skip to content

Conversation

crs2007
Copy link

@crs2007 crs2007 commented Jul 23, 2025

Pull Request: TVP Schema Name Fix and Request Timeout Improvements

Overview

This PR addresses and resolves the following issues:

  • #1759: TVP Parameter Schema Name Not Included in sp_executesql @params.
  • MS SQL Server query timeout: "request failed to complete in 15000ms".

Key Changes

  • TVP Schema Name Fix:
    When passing Table-Valued Parameters (TVPs), the schema and type name are now correctly preserved and included in the parameter declaration. This ensures that sp_executesql receives the fully qualified type name (including schema), resolving issues with custom TVP types. See lib/tedious/request.js.
  • Request Timeout Handling:
    • Standardized and enforced default values for requestTimeout and connectionTimeout across both Tedious and msnodesqlv8 drivers.
    • Ensured timeout values are correctly parsed and propagated from configuration and connection strings.
    • For Tedious, per-request timeout is now explicitly assigned (lib/tedious/request.js:502).
    • For msnodesqlv8, query_timeout is set in seconds, derived from config.requestTimeout.
    • Improved error handling for timeouts and connection errors, reducing unhandled promise rejections and improving reliability.

Impact

  • TVP parameters with schema-qualified type names now work correctly with sp_executesql and custom types.
  • Prevents premature query failures due to misconfigured or missing timeout values.
  • Ensures consistent behavior for request and connection timeouts across all supported drivers.
  • Resolves user-reported issues with timeouts not being respected or propagated.

Improves TVP type name handling to avoid schema duplication and assigns per-request timeout to tedious Request if set. Adds tests for long requestTimeout and TVP with schema-qualified names, and increases Mocha test timeouts for long-running tests.
Copy link
Collaborator

@dhensby dhensby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've gone and rebased this as well as reworded the commits and fixed the code linting issues.

I'm a bit concerned about the tests here, and I'm not sure the TVP fix is fixed...

Comment on lines +1856 to +1865
'Fix default requestTimeout is above 15s' (done) {
const req = new TestRequest()
req.requestTimeout = 25000 // 25 seconds
const start = Date.now()
req.query("WAITFOR DELAY '00:00:20.000';").then(result => {
const elapsed = Date.now() - start
assert.ok(!result.error, 'Should not error for long WAITFOR DELAY with high timeout')
assert(elapsed >= 20000, 'Query should take at least 20 seconds')
done()
}).catch(done)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's good for us to add 20+ seconds to our test suite to test that we can set a high timeout on the request.

I'd rather we just set a low timeout (1 second, 2 seconds?!) and keep our test suite as fast as reasonably possible.

Comment on lines +1868 to +1890
(async () => {
let pool
try {
pool = await sql.connect(readConfig())
const request = pool.request()
const tvp = new sql.Table('AI.UDT_StringArray')
tvp.columns.add('Name', sql.NVarChar(128), { nullable: false })
tvp.rows.add('TestValue1')
tvp.rows.add('TestValue2')
request.input('InputList', tvp)
await request.execute('AI.USP_TestProcedure')
} catch (err) {
if (err && /Cannot find data type UDT_StringArray/.test(err.message)) {
return done()
}
if (err && /could not find|does not exist|invalid object/i.test(err.message)) {
return done()
}
done(err)
} finally {
if (pool) await sql.close()
}
})()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a nitpick, but I don't like this mixed async/callback style. The tests are written in an outdated way, but this mixing feels (and looks) nasty.

Also, isn't there already a pool ready, so there's no need to be initiating a pool here? Could we be using assert.match()?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants