Skip to content

Commit a8723fb

Browse files
committed
fix: treat bigint as string in msnodesqlv8 driver
BigInt types will lose precision if they are above the MAX_SAFE_INTEGER value. A work around for this is to use strings to represent the numbers instead.
1 parent c4544be commit a8723fb

File tree

8 files changed

+79
-38
lines changed

8 files changed

+79
-38
lines changed

CHANGELOG.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Unreleased
2+
-------------------
3+
[fix] BigInt type in nodemsqlv8 now treated as strings in parity with the tedious drive ([#1387](https://github.com/tediousjs/node-mssql/pull/1387))
4+
15
v10.0.0 (2023-09-06)
26
-------------------
37
[change] Upgrade tedious to v16 ([#1547](https://github.com/tediousjs/node-mssql/pull/1547))
@@ -69,7 +73,7 @@ v8.1.1 (2022-05-18)
6973

7074
v8.1.0 (2022-04-06)
7175
-------------------
72-
[new] MSSQL CLI tool now accepts some options to allow overriding config file ((#1381](https://github.com/tediousjs/node-mssql/pull/1381))
76+
[new] MSSQL CLI tool now accepts some options to allow overriding config file ([#1381](https://github.com/tediousjs/node-mssql/pull/1381))
7377
[fix] nodemsqlv8 driver tests working against Node 10 ([#1368](https://github.com/tediousjs/node-mssql/pull/1368))
7478

7579
v8.0.2 (2022-02-07)

lib/msnodesqlv8/connection-pool.js

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class ConnectionPool extends BaseConnectionPool {
4747
return reject(err)
4848
}
4949

50+
tds.setUseNumericString(true)
51+
5052
IDS.add(tds, 'Connection', connedtionId)
5153
tds.setUseUTC(this.config.options.useUTC)
5254
debug('connection(%d): established', IDS.get(tds))

lib/msnodesqlv8/request.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const castParameter = function (value, type) {
3131
case TYPES.NChar:
3232
case TYPES.Xml:
3333
case TYPES.Text:
34+
case TYPES.BigInt:
3435
case TYPES.NText:
3536
if ((typeof value !== 'string') && !(value instanceof String)) {
3637
value = value.toString()
@@ -39,7 +40,6 @@ const castParameter = function (value, type) {
3940

4041
case TYPES.Int:
4142
case TYPES.TinyInt:
42-
case TYPES.BigInt:
4343
case TYPES.SmallInt:
4444
if ((typeof value !== 'number') && !(value instanceof Number)) {
4545
value = parseInt(value)

test/cleanup.sql

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ if exists (select * from sys.tables where name = 'bulk_table5')
5252
if exists (select * from sys.tables where name = 'rowsaffected_test')
5353
exec('drop table [dbo].[rowsaffected_test]')
5454

55+
if exists (select * from sys.tables where name = 'bignumbers')
56+
exec('drop table [dbo].[bignumbers]')
57+
5558
if exists (select * from sys.tables where name = 'streaming')
5659
exec('drop table [dbo].[streaming]')
5760

test/common/tests.js

+24
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,30 @@ module.exports = (sql, driver) => {
12761276
}).catch(done)
12771277
},
12781278

1279+
'BigInt parameters' (done) {
1280+
const req = new TestRequest()
1281+
req.input('bignumber', sql.BigInt, '9223372036854775807')
1282+
req.query('INSERT INTO [dbo].[bignumbers] (bignumber) VALUES (@bignumber)')
1283+
.then(() => {
1284+
const req2 = new TestRequest()
1285+
return req2.query('SELECT * FROM [dbo].[bignumbers]')
1286+
})
1287+
.then((result) => {
1288+
assert.strictEqual(result.recordsets.length, 1)
1289+
assert.strictEqual(result.recordset[0].bignumber, '9223372036854775807')
1290+
done()
1291+
})
1292+
.catch(done)
1293+
},
1294+
1295+
'BigInt casted types' (done) {
1296+
const req = new TestRequest()
1297+
req.query('SELECT cast(9223372036854775807 AS BigInt) as bignumber').then(result => {
1298+
assert.strictEqual(result.recordset[0].bignumber, '9223372036854775807')
1299+
done()
1300+
}).catch(done)
1301+
},
1302+
12791303
'dataLength type correction' (done) {
12801304
sql.on('error', err => console.error(err))
12811305
const req = new TestRequest()

test/msnodesqlv8/msnodesqlv8.js

+20-18
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ const sql = require('../../msnodesqlv8')
88
const TESTS = require('../common/tests.js')(sql, 'msnodesqlv8')
99
const TIMES = require('../common/times.js')(sql, 'msnodesqlv8')
1010
const versionHelper = require('../common/versionhelper')
11+
const { readFileSync } = require('node:fs')
1112

1213
const config = function () {
13-
const cfg = JSON.parse(require('node:fs').readFileSync(join(__dirname, '../.mssql.json')))
14+
const cfg = JSON.parse(readFileSync(join(__dirname, '../.mssql.json')))
1415
cfg.driver = 'msnodesqlv8'
1516
return cfg
1617
}
@@ -19,23 +20,22 @@ let connection1 = null
1920
let connection2 = null
2021

2122
describe('msnodesqlv8', function () {
22-
before(done =>
23-
sql.connect(config(), function (err) {
24-
if (err) return done(err)
25-
26-
let req = new sql.Request()
27-
req.batch(require('node:fs').readFileSync(join(__dirname, '../cleanup.sql'), 'utf8'), function (err) {
28-
if (err) return done(err)
29-
30-
req = new sql.Request()
31-
req.batch(require('node:fs').readFileSync(join(__dirname, '../prepare.sql'), 'utf8'), function (err) {
32-
if (err) return done(err)
33-
34-
sql.close(done)
23+
before(done => {
24+
try {
25+
sql.connect(config())
26+
.then(() => {
27+
return new sql.Request().query(readFileSync(join(__dirname, '../cleanup.sql'), 'utf8'))
3528
})
36-
})
37-
})
38-
)
29+
.then(() => {
30+
return new sql.Request().query(readFileSync(join(__dirname, '../prepare.sql'), 'utf8'))
31+
})
32+
.catch(done)
33+
.then(() => sql.close())
34+
.then(() => done())
35+
} catch (e) {
36+
done(e)
37+
}
38+
})
3939
afterEach(() => sql.valueHandler.clear())
4040

4141
describe('basic test suite', function () {
@@ -91,6 +91,8 @@ describe('msnodesqlv8', function () {
9191
it('connection healthy works', done => TESTS['connection healthy works'](config(), done))
9292
it('healthy connection goes bad', done => TESTS['healthy connection goes bad'](config(), done))
9393
it('request timeout', done => TESTS['request timeout'](done))
94+
it('BigInt parameters', done => TESTS['BigInt parameters'](done))
95+
it('BigInt casted types', done => TESTS['BigInt casted types'](done))
9496
it('dataLength type correction', done => TESTS['dataLength type correction'](done))
9597
it('chunked xml support', done => TESTS['chunked xml support'](done))
9698

@@ -245,7 +247,7 @@ describe('msnodesqlv8', function () {
245247
if (err) return done(err)
246248

247249
const req = new sql.Request()
248-
req.query(require('node:fs').readFileSync(join(__dirname, '../cleanup.sql'), 'utf8'), function (err) {
250+
req.query(readFileSync(join(__dirname, '../cleanup.sql'), 'utf8'), function (err) {
249251
if (err) return done(err)
250252

251253
sql.close(done)

test/prepare.sql

+4
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ exec('create table [dbo].[rowsaffected_test] (
145145
a int not null
146146
)')
147147

148+
exec('create table [dbo].[bignumbers] (
149+
bignumber bigint
150+
)')
151+
148152
;with nums as
149153
(
150154
select 0 AS n

test/tedious/tedious.js

+20-18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
const sql = require('../../tedious.js')
66
const assert = require('node:assert')
77
const { join } = require('node:path')
8+
const { readFileSync } = require('node:fs')
89

910
const TESTS = require('../common/tests.js')(sql, 'tedious')
1011
const TIMES = require('../common/times.js')(sql, 'tedious')
@@ -16,7 +17,7 @@ if (parseInt(process.version.match(/^v(\d+)\./)[1]) > 0) {
1617
}
1718

1819
const config = function () {
19-
const cfg = JSON.parse(require('node:fs').readFileSync(join(__dirname, '../.mssql.json')))
20+
const cfg = JSON.parse(readFileSync(join(__dirname, '../.mssql.json')))
2021
cfg.driver = 'tedious'
2122
return cfg
2223
}
@@ -25,23 +26,22 @@ let connection1 = null
2526
let connection2 = null
2627

2728
describe('tedious', () => {
28-
before(done =>
29-
sql.connect(config(), err => {
30-
if (err) return done(err)
31-
32-
let req = new sql.Request()
33-
req.query(require('node:fs').readFileSync(join(__dirname, '../cleanup.sql'), 'utf8'), err => {
34-
if (err) return done(err)
35-
36-
req = new sql.Request()
37-
req.query(require('node:fs').readFileSync(join(__dirname, '../prepare.sql'), 'utf8'), err => {
38-
if (err) return done(err)
39-
40-
sql.close(done)
29+
before(done => {
30+
try {
31+
sql.connect(config())
32+
.then(() => {
33+
return new sql.Request().query(readFileSync(join(__dirname, '../cleanup.sql'), 'utf8'))
4134
})
42-
})
43-
})
44-
)
35+
.then(() => {
36+
return new sql.Request().query(readFileSync(join(__dirname, '../prepare.sql'), 'utf8'))
37+
})
38+
.catch(done)
39+
.then(() => sql.close())
40+
.then(() => done())
41+
} catch (e) {
42+
done(e)
43+
}
44+
})
4545
afterEach(() => sql.valueHandler.clear())
4646

4747
describe('basic test suite', () => {
@@ -100,6 +100,8 @@ describe('tedious', () => {
100100
it('connection healthy works', done => TESTS['connection healthy works'](config(), done))
101101
it('healthy connection goes bad', done => TESTS['healthy connection goes bad'](config(), done))
102102
it('request timeout', done => TESTS['request timeout'](done, 'tedious', /Timeout: Request failed to complete in 1000ms/))
103+
it('BigInt parameters', done => TESTS['BigInt parameters'](done))
104+
it('BigInt casted types', done => TESTS['BigInt casted types'](done))
103105
it('dataLength type correction', done => TESTS['dataLength type correction'](done))
104106
it('type validation', done => TESTS['type validation']('query', done))
105107
it('type validation (batch)', done => TESTS['type validation']('batch', done))
@@ -345,7 +347,7 @@ describe('tedious', () => {
345347
if (err) return done(err)
346348

347349
const req = new sql.Request()
348-
req.query(require('node:fs').readFileSync(join(__dirname, '../cleanup.sql'), 'utf8'), function (err) {
350+
req.query(readFileSync(join(__dirname, '../cleanup.sql'), 'utf8'), function (err) {
349351
if (err) return done(err)
350352

351353
sql.close(done)

0 commit comments

Comments
 (0)