mssql 4.0.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.txt CHANGED
@@ -1,3 +1,22 @@
1
+ v4.1.0 (2017-09-29)
2
+ -------------------
3
+ [new] Adding support for the MultiSubnetFailover option in connection strings (Paul Kehrer)
4
+ [new] Add request timeout support for msnodesqlv8 queries (Michael Parque)
5
+ [fix] Fix type inference of non-integer numbers (Andrew Crites)
6
+ [fix] Set acquireTimeout on generic pool (Karl Wiggisser)
7
+
8
+ v4.0.4 (2017-04-25)
9
+ -------------------
10
+ [fix] Fix auto-closing of idle connections
11
+
12
+ v4.0.3 (2017-04-25)
13
+ -------------------
14
+ [fix] Fixed broken CLI & debugging
15
+
16
+ v4.0.2 (2017-04-19)
17
+ -------------------
18
+ [fix] Fixed broken JSON parser
19
+
1
20
  v4.0.1 (2017-04-02)
2
21
  -------------------
3
22
  [fix] Fixed stream in pipe mode
package/README.md CHANGED
@@ -40,7 +40,7 @@ If you're on Windows Azure, add `?encrypt=true` to your connection string. See [
40
40
 
41
41
  ### Examples
42
42
 
43
- * [Async/Await](#async-await)
43
+ * [Async/Await](#asyncawait)
44
44
  * [Promises](#promises)
45
45
  * [ES6 Tagged template literals](#es6-tagged-template-literals)
46
46
  * [Callbacks](#callbacks)
@@ -59,7 +59,7 @@ If you're on Windows Azure, add `?encrypt=true` to your connection string. See [
59
59
 
60
60
  ### Connections
61
61
 
62
- * [ConnectionPool](#connectionpool)
62
+ * [ConnectionPool](#connections-1)
63
63
  * [connect](#connect-callback)
64
64
  * [close](#close)
65
65
 
@@ -168,7 +168,7 @@ sql.connect(config).then(pool => {
168
168
  .input('input_parameter', sql.Int, value)
169
169
  .query('select * from mytable where id = @input_parameter')
170
170
  }).then(result => {
171
- console.dir(recordset)
171
+ console.dir(result)
172
172
 
173
173
  // Stored procedure
174
174
 
@@ -189,7 +189,7 @@ sql.on('error', err => {
189
189
 
190
190
  Native Promise is used by default. You can easily change this with `sql.Promise = require('myownpromisepackage')`.
191
191
 
192
- **ES6 Tagged template literals**
192
+ ### ES6 Tagged template literals
193
193
 
194
194
  ```javascript
195
195
  const sql = require('mssql')
@@ -301,7 +301,7 @@ pool1.on('error', err => {
301
301
  // ... error handler
302
302
  })
303
303
 
304
- const pool2 = new sql.Connection(config, err => {
304
+ const pool2 = new sql.ConnectionPool(config, err => {
305
305
  // ... error checks
306
306
 
307
307
  // Stored Procedure
@@ -316,7 +316,7 @@ const pool2 = new sql.Connection(config, err => {
316
316
  })
317
317
  })
318
318
 
319
- pool1.on('error', err => {
319
+ pool2.on('error', err => {
320
320
  // ... error handler
321
321
  })
322
322
  ```
@@ -360,13 +360,15 @@ const config = {
360
360
  - **domain** - Once you set domain, driver will connect to SQL Server using domain login.
361
361
  - **database** - Database to connect to (default: dependent on server configuration).
362
362
  - **connectionTimeout** - Connection timeout in ms (default: `15000`).
363
- - **requestTimeout** - Request timeout in ms (default: `15000`).
363
+ - **requestTimeout** - Request timeout in ms (default: `15000`). NOTE: msnodesqlv8 driver doesn't support timeouts < 1 second.
364
364
  - **stream** - Stream recordsets/rows instead of returning them all at once as an argument of callback (default: `false`). You can also enable streaming for each request independently (`request.stream = true`). Always set to `true` if you plan to work with large amount of rows.
365
365
  - **parseJSON** - Parse JSON recordsets to JS objects (default: `false`). For more information please see section [JSON support](#json-support).
366
366
  - **pool.max** - The maximum number of connections there can be in the pool (default: `10`).
367
367
  - **pool.min** - The minimum of connections there can be in the pool (default: `0`).
368
368
  - **pool.idleTimeoutMillis** - The Number of milliseconds before closing an unused connection (default: `30000`).
369
369
 
370
+ Complete list of pool options can be found [here](https://github.com/coopernurse/node-pool).
371
+
370
372
  ### Formats
371
373
 
372
374
  In addition to configuration object there is an option to pass config as a connection string. Two formats of connection string are supported.
@@ -725,7 +727,7 @@ You can enable multiple recordsets in queries with the `request.multiple = true`
725
727
 
726
728
  ---------------------------------------
727
729
 
728
- ### bulk(table, [callback])
730
+ ### bulk (table, [callback])
729
731
 
730
732
  Perform a bulk insert.
731
733
 
@@ -1540,7 +1542,6 @@ request.query('select @myval as myval', (err, result) => {
1540
1542
  - msnodesqlv8 has problem with errors during transactions - [reported](https://github.com/patriksimek/node-mssql/issues/77).
1541
1543
  - msnodesqlv8 doesn't timeout the connection reliably - [reported](https://github.com/TimelordUK/node-sqlserver-v8/issues/9).
1542
1544
  - msnodesqlv8 doesn't support [TVP](#table-valued-parameter-tvp) data type.
1543
- - msnodesqlv8 doesn't support Variant data type.
1544
1545
  - msnodesqlv8 doesn't support request timeout.
1545
1546
  - msnodesqlv8 doesn't support request cancellation.
1546
1547
  - msnodesqlv8 doesn't support [detailed SQL errors](#detailed-sql-errors).
package/lib/base.js CHANGED
@@ -66,14 +66,12 @@ let getTypeByValue = function (value) {
66
66
  return TYPES.NVarChar
67
67
 
68
68
  case 'number':
69
- for (item of Array.from(map)) {
70
- if (item.js === Number) {
71
- return item.sql
72
- }
69
+ if (value % 1 === 0) {
70
+ return TYPES.Int
71
+ } else {
72
+ return TYPES.Float
73
73
  }
74
74
 
75
- return TYPES.Int
76
-
77
75
  case 'boolean':
78
76
  for (item of Array.from(map)) {
79
77
  if (item.js === Boolean) {
@@ -171,7 +169,7 @@ class ConnectionPool extends EventEmitter {
171
169
  debug('conn: acquire')
172
170
 
173
171
  if (typeof callback === 'function') {
174
- this._acquire().then(connection => callback(null, connection)).catch(callback)
172
+ this._acquire().then(connection => callback(null, connection, this.config)).catch(callback)
175
173
  return this
176
174
  }
177
175
 
@@ -253,9 +251,10 @@ class ConnectionPool extends EventEmitter {
253
251
  }, Object.assign({
254
252
  max: 10,
255
253
  min: 0,
254
+ acquireTimeoutMillis: this.config.connectionTimeout || this.config.timeout || 15000,
255
+ evictionRunIntervalMillis: 1000,
256
256
  idleTimeoutMillis: 30000,
257
- testOnBorrow: true,
258
- autostart: false
257
+ testOnBorrow: true
259
258
  }, this.config.pool))
260
259
 
261
260
  this.pool.on('factoryCreateError', this.emit.bind(this, 'error'))
@@ -414,7 +413,7 @@ class PreparedStatement extends EventEmitter {
414
413
  debug('ps: acquire ok')
415
414
 
416
415
  this._activeRequest = request
417
- setImmediate(callback, null, this._acquiredConnection)
416
+ setImmediate(callback, null, this._acquiredConnection, this._acquiredConfig)
418
417
  return this
419
418
  }
420
419
 
@@ -543,10 +542,11 @@ class PreparedStatement extends EventEmitter {
543
542
 
544
543
  this.statement = statement || this.statement
545
544
 
546
- this.parent.acquire(this, (err, connection) => {
545
+ this.parent.acquire(this, (err, connection, config) => {
547
546
  if (err) return callback(err)
548
547
 
549
548
  this._acquiredConnection = connection
549
+ this._acquiredConfig = config
550
550
 
551
551
  const req = new driver.Request(this)
552
552
  req.stream = false
@@ -564,6 +564,7 @@ class PreparedStatement extends EventEmitter {
564
564
  if (err) {
565
565
  this.parent.release(this._acquiredConnection)
566
566
  this._acquiredConnection = null
567
+ this._acquiredConfig = null
567
568
 
568
569
  return callback(err)
569
570
  }
@@ -678,6 +679,7 @@ class PreparedStatement extends EventEmitter {
678
679
 
679
680
  this.parent.release(this._acquiredConnection)
680
681
  this._acquiredConnection = null
682
+ this._acquiredConfig = null
681
683
  this._handle = 0
682
684
  this.prepared = false
683
685
 
@@ -742,7 +744,7 @@ class Transaction extends EventEmitter {
742
744
  debug('tran: acquire ok')
743
745
 
744
746
  this._activeRequest = request
745
- setImmediate(callback, null, this._acquiredConnection)
747
+ setImmediate(callback, null, this._acquiredConnection, this._acquiredConfig)
746
748
  return this
747
749
  }
748
750
 
@@ -1419,6 +1421,7 @@ class ConnectionError extends Error {
1419
1421
  super(message.message)
1420
1422
  this.code = message.code || code
1421
1423
 
1424
+ Error.captureStackTrace(this, this.constructor)
1422
1425
  Object.defineProperty(this, 'originalError', {enumerable: true, value: message})
1423
1426
  } else {
1424
1427
  super(message)
@@ -1446,6 +1449,7 @@ class TransactionError extends Error {
1446
1449
  super(message.message)
1447
1450
  this.code = message.code || code
1448
1451
 
1452
+ Error.captureStackTrace(this, this.constructor)
1449
1453
  Object.defineProperty(this, 'originalError', {enumerable: true, value: message})
1450
1454
  } else {
1451
1455
  super(message)
@@ -1492,6 +1496,7 @@ class RequestError extends Error {
1492
1496
  this.state = message.sqlstate // err.sqlstate is returned by msnodesql driver
1493
1497
  }
1494
1498
 
1499
+ Error.captureStackTrace(this, this.constructor)
1495
1500
  Object.defineProperty(this, 'originalError', {enumerable: true, value: message})
1496
1501
  } else {
1497
1502
  super(message)
@@ -1522,6 +1527,7 @@ class PreparedStatementError extends Error {
1522
1527
  super(message.message)
1523
1528
  this.code = message.code || code
1524
1529
 
1530
+ Error.captureStackTrace(this, this.constructor)
1525
1531
  Object.defineProperty(this, 'originalError', {enumerable: true, value: message})
1526
1532
  } else {
1527
1533
  super(message)
@@ -1551,7 +1557,8 @@ module.exports = {
1551
1557
  ISOLATION_LEVEL,
1552
1558
  TYPES,
1553
1559
  MAX: 65535, // (1 << 16) - 1
1554
- map
1560
+ map,
1561
+ getTypeByValue
1555
1562
  }
1556
1563
  }
1557
1564
 
package/lib/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require('fs')
4
4
  const path = require('path')
5
- const sql = require('./main')
5
+ const sql = require('./tedious')
6
6
 
7
7
  const exit = process.exit
8
8
  const write = text => process.stdout.write(text)
@@ -75,7 +75,7 @@ const parseConnectionString = function (string) {
75
75
  const parsed = {}
76
76
  const original = {}
77
77
 
78
- Object.defineProperty(parsed, '__original__', {value: original})
78
+ Object.defineProperty(parsed, '__original__', { value: original })
79
79
  Object.defineProperty(parsed, 'toString', {
80
80
  value () {
81
81
  const out = []
@@ -96,7 +96,7 @@ const parseConnectionString = function (string) {
96
96
  if (parsing === 'name') {
97
97
  buffer = buffer.trim()
98
98
  param = buffer.toLowerCase()
99
- original[param] = {name: buffer}
99
+ original[param] = { name: buffer }
100
100
  parsing = 'value'
101
101
  buffer = ''
102
102
  } else {
@@ -210,10 +210,10 @@ const resolveConnectionString = function (string, driver) {
210
210
  parsed.driver = 'SQL Server Native Client 11.0'
211
211
 
212
212
  if (parsed.__original__) {
213
- parsed.__original__.driver = {name: 'Driver', escape: ['{', '}']}
213
+ parsed.__original__.driver = { name: 'Driver', escape: ['{', '}'] }
214
214
  }
215
215
 
216
- return {connectionString: parsed.toString()}
216
+ return { connectionString: parsed.toString() }
217
217
  }
218
218
 
219
219
  let user = parsed.uid || parsed.uid || parsed['user id']
@@ -241,6 +241,10 @@ const resolveConnectionString = function (string, driver) {
241
241
  config.requestTimeout = parseInt(config.requestTimeout, 10)
242
242
  }
243
243
 
244
+ if (parsed.multisubnetfailover != null) {
245
+ config.options.multiSubnetFailover = parsed.multisubnetfailover.toLowerCase() === 'true'
246
+ }
247
+
244
248
  if (/^(.*)\\(.*)$/.exec(user)) {
245
249
  config.domain = RegExp.$1
246
250
  user = RegExp.$2
@@ -151,6 +151,10 @@ class ConnectionPool extends base.ConnectionPool {
151
151
  defaultConnectionString = CONNECTION_STRING_NAMED_INSTANCE
152
152
  }
153
153
 
154
+ if (this.config.requestTimeout == null) {
155
+ this.config.requestTimeout = 15000
156
+ }
157
+
154
158
  const cfg = {
155
159
  conn_str: this.config.connectionString || defaultConnectionString,
156
160
  conn_timeout: (this.config.connectionTimeout || 15000) / 1000
@@ -205,10 +209,11 @@ class Transaction extends base.Transaction {
205
209
 
206
210
  debug('tran: begin')
207
211
 
208
- this.parent.acquire(this, (err, connection) => {
212
+ this.parent.acquire(this, (err, connection, config) => {
209
213
  if (err) return callback(err)
210
214
 
211
215
  this._acquiredConnection = connection
216
+ this._acquiredConfig = config
212
217
 
213
218
  const req = new Request(this)
214
219
  req.stream = false
@@ -216,6 +221,7 @@ class Transaction extends base.Transaction {
216
221
  if (err) {
217
222
  this.parent.release(this._acquiredConnection)
218
223
  this._acquiredConnection = null
224
+ this._acquiredConfig = null
219
225
 
220
226
  return callback(err)
221
227
  }
@@ -241,6 +247,7 @@ class Transaction extends base.Transaction {
241
247
 
242
248
  this.parent.release(this._acquiredConnection)
243
249
  this._acquiredConnection = null
250
+ this._acquiredConfig = null
244
251
 
245
252
  if (!err) debug('tran: commit ok')
246
253
 
@@ -262,6 +269,7 @@ class Transaction extends base.Transaction {
262
269
 
263
270
  this.parent.release(this._acquiredConnection)
264
271
  this._acquiredConnection = null
272
+ this._acquiredConfig = null
265
273
 
266
274
  if (!err) debug('tran: rollback ok')
267
275
 
@@ -406,7 +414,7 @@ class Request extends base.Request {
406
414
  }
407
415
  }
408
416
 
409
- this.parent.acquire(this, (err, connection) => {
417
+ this.parent.acquire(this, (err, connection, config) => {
410
418
  if (err) return callback(err)
411
419
 
412
420
  debug('req:connection acquired')
@@ -415,15 +423,18 @@ class Request extends base.Request {
415
423
  for (let name in this.parameters) {
416
424
  let param = this.parameters[name]
417
425
  if (param.io === 1) {
418
- params.push(castParameter(param.value, param.type))
426
+ params.push(castParameter(param.value, param.type, param))
419
427
  }
420
428
  }
421
429
 
422
- const req = connection.queryRaw(command, params)
430
+ const req = connection.queryRaw({
431
+ query_str: command,
432
+ query_timeout: config.requestTimeout / 1000 // msnodesqlv8 timeouts are in seconds (<1 second not supported)
433
+ }, params)
423
434
  req.on('meta', metadata => {
424
435
  if (row) {
425
436
  if (isChunkedRecordset) {
426
- if ((columns[0].name === JSON_COLUMN_ID) && (this.connection.config.parseJSON === true)) {
437
+ if ((columns[0].name === JSON_COLUMN_ID) && (config.parseJSON === true)) {
427
438
  try {
428
439
  row = JSON.parse(chunksBuffer.join(''))
429
440
  if (!this.stream) { recordsets[recordsets.length - 1][0] = row }
@@ -531,7 +542,7 @@ class Request extends base.Request {
531
542
  if (!this._nested) {
532
543
  if (row) {
533
544
  if (isChunkedRecordset) {
534
- if ((columns[0].name === JSON_COLUMN_ID) && (this.connection.config.parseJSON === true)) {
545
+ if ((columns[0].name === JSON_COLUMN_ID) && (config.parseJSON === true)) {
535
546
  try {
536
547
  row = JSON.parse(chunksBuffer.join(''))
537
548
  if (!this.stream) { recordsets[recordsets.length - 1][0] = row }
package/lib/tedious.js CHANGED
@@ -230,7 +230,7 @@ class ConnectionPool extends base.ConnectionPool {
230
230
  })
231
231
 
232
232
  if (this.config.debug) {
233
- tedious.on('debug', msg => this._debug(msg))
233
+ tedious.on('debug', this.emit.bind(this, 'debug', tedious))
234
234
  }
235
235
  })
236
236
  }
@@ -267,6 +267,7 @@ class Transaction extends base.Transaction {
267
267
 
268
268
  this._acquiredConnection.removeListener('rollbackTransaction', this._abort)
269
269
  this._acquiredConnection = null
270
+ this._acquiredConfig = null
270
271
  this._aborted = true
271
272
 
272
273
  this.emit('rollback', true)
@@ -280,11 +281,12 @@ class Transaction extends base.Transaction {
280
281
 
281
282
  debug('tran: begin')
282
283
 
283
- this.parent.acquire(this, (err, connection) => {
284
+ this.parent.acquire(this, (err, connection, config) => {
284
285
  if (err) return callback(err)
285
286
 
286
287
  this._acquiredConnection = connection
287
288
  this._acquiredConnection.on('rollbackTransaction', this._abort)
289
+ this._acquiredConfig = config
288
290
 
289
291
  connection.beginTransaction(err => {
290
292
  if (err) err = new base.TransactionError(err)
@@ -309,6 +311,7 @@ class Transaction extends base.Transaction {
309
311
  this._acquiredConnection.removeListener('rollbackTransaction', this._abort)
310
312
  this.parent.release(this._acquiredConnection)
311
313
  this._acquiredConnection = null
314
+ this._acquiredConfig = null
312
315
 
313
316
  if (!err) debug('tran: commit ok')
314
317
 
@@ -329,6 +332,7 @@ class Transaction extends base.Transaction {
329
332
  this._acquiredConnection.removeListener('rollbackTransaction', this._abort)
330
333
  this.parent.release(this._acquiredConnection)
331
334
  this._acquiredConnection = null
335
+ this._acquiredConfig = null
332
336
 
333
337
  if (!err) debug('tran: rollback ok')
334
338
 
@@ -547,7 +551,7 @@ class Request extends base.Request {
547
551
  })
548
552
  }
549
553
 
550
- this.parent.acquire(this, (err, connection) => {
554
+ this.parent.acquire(this, (err, connection, config) => {
551
555
  if (err) return callback(err)
552
556
 
553
557
  let row
@@ -646,7 +650,7 @@ class Request extends base.Request {
646
650
  if (Object.keys(columns).length === 0) return
647
651
 
648
652
  if (isChunkedRecordset) {
649
- if (columns[JSON_COLUMN_ID] && this.connection.config.parseJSON === true) {
653
+ if (columns[JSON_COLUMN_ID] && config.parseJSON === true) {
650
654
  try {
651
655
  row = JSON.parse(chunksBuffer.join(''))
652
656
  } catch (ex) {
@@ -844,7 +848,7 @@ class Request extends base.Request {
844
848
  errors.push(err)
845
849
  }
846
850
 
847
- this.parent.acquire(this, (err, connection) => {
851
+ this.parent.acquire(this, (err, connection, config) => {
848
852
  if (err) return callback(err)
849
853
 
850
854
  let row
@@ -951,7 +955,7 @@ class Request extends base.Request {
951
955
  if (Object.keys(columns).length === 0) return
952
956
 
953
957
  if (isChunkedRecordset) {
954
- if (columns[JSON_COLUMN_ID] && connection.config.parseJSON === true) {
958
+ if (columns[JSON_COLUMN_ID] && config.parseJSON === true) {
955
959
  try {
956
960
  row = JSON.parse(chunksBuffer.join(''))
957
961
  } catch (ex) {
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "azure",
22
22
  "node-mssql"
23
23
  ],
24
- "version": "4.0.1",
24
+ "version": "4.1.0",
25
25
  "main": "index.js",
26
26
  "repository": {
27
27
  "type": "git",
package/.npmignore DELETED
@@ -1,4 +0,0 @@
1
- node_modules
2
- .DS_Store
3
- .vscode
4
- test