mssql 7.2.0 → 8.0.1

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/lib/cli.js CHANGED
@@ -1,113 +1,113 @@
1
- 'use strict'
2
-
3
- const fs = require('fs')
4
- const path = require('path')
5
- const sql = require('./tedious')
6
-
7
- const exit = process.exit
8
- const write = text => process.stdout.write(text)
9
- Buffer.prototype.toJSON = () => {
10
- return `0x${this.toString('hex')}`
11
- }
12
-
13
- // Resolve config path
14
-
15
- let cfgPath = path.resolve(process.argv[2] || process.cwd())
16
- if (fs.lstatSync(cfgPath).isDirectory()) {
17
- cfgPath = path.resolve(cfgPath, './.mssql.json')
18
- }
19
- if (!fs.existsSync(cfgPath)) {
20
- console.error('Config file not found.')
21
- exit(1)
22
- }
23
-
24
- // Config checks & parse
25
-
26
- let config
27
- try {
28
- config = fs.readFileSync(cfgPath)
29
- } catch (err) {
30
- console.error(`Failed to load config file. ${err.message}`)
31
- exit(1)
32
- }
33
-
34
- try {
35
- config = JSON.parse(config)
36
- } catch (err) {
37
- console.error(`Failed to parse config file. ${err.message}`)
38
- exit(1)
39
- }
40
-
41
- // Read stdin
42
-
43
- const buffer = []
44
-
45
- process.stdin.setEncoding('utf8')
46
- process.stdin.on('readable', () => buffer.push(process.stdin.read()))
47
-
48
- process.stdin.on('end', () => {
49
- const statement = buffer.join('')
50
- let rst = 0
51
- let index = 0
52
-
53
- if (!statement.length) {
54
- console.error('Statement is empty.')
55
- exit(1)
56
- }
57
-
58
- sql.connect(config, err => {
59
- if (err) {
60
- console.error(err.message)
61
- exit(1)
62
- }
63
-
64
- write('[')
65
-
66
- const request = new sql.Request()
67
- request.stream = true
68
- request.on('recordset', () => {
69
- index = 0
70
- if (rst++ > 0) {
71
- write('],')
72
- }
73
-
74
- return write('[')
75
- })
76
-
77
- request.on('error', err => {
78
- console.error(err.message)
79
- sql.close()
80
- return exit(1)
81
- })
82
-
83
- request.on('row', row => {
84
- if (index++ > 0) {
85
- write(',')
86
- }
87
-
88
- return write(JSON.stringify(row))
89
- })
90
-
91
- request.on('done', () => {
92
- if (rst > 0) {
93
- write(']')
94
- }
95
-
96
- write(']\n')
97
- sql.close()
98
- return exit(0)
99
- })
100
-
101
- request.query(statement)
102
- })
103
- })
104
-
105
- process.on('uncaughtException', err => {
106
- if (err.code === 'EPIPE') {
107
- console.error('Failed to pipe output stream.')
108
- } else {
109
- console.error(err.message)
110
- }
111
-
112
- exit(1)
113
- })
1
+ 'use strict'
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+ const sql = require('./tedious')
6
+
7
+ const exit = process.exit
8
+ const write = text => process.stdout.write(text)
9
+ Buffer.prototype.toJSON = () => {
10
+ return `0x${this.toString('hex')}`
11
+ }
12
+
13
+ // Resolve config path
14
+
15
+ let cfgPath = path.resolve(process.argv[2] || process.cwd())
16
+ if (fs.lstatSync(cfgPath).isDirectory()) {
17
+ cfgPath = path.resolve(cfgPath, './.mssql.json')
18
+ }
19
+ if (!fs.existsSync(cfgPath)) {
20
+ console.error('Config file not found.')
21
+ exit(1)
22
+ }
23
+
24
+ // Config checks & parse
25
+
26
+ let config
27
+ try {
28
+ config = fs.readFileSync(cfgPath)
29
+ } catch (err) {
30
+ console.error(`Failed to load config file. ${err.message}`)
31
+ exit(1)
32
+ }
33
+
34
+ try {
35
+ config = JSON.parse(config)
36
+ } catch (err) {
37
+ console.error(`Failed to parse config file. ${err.message}`)
38
+ exit(1)
39
+ }
40
+
41
+ // Read stdin
42
+
43
+ const buffer = []
44
+
45
+ process.stdin.setEncoding('utf8')
46
+ process.stdin.on('readable', () => buffer.push(process.stdin.read()))
47
+
48
+ process.stdin.on('end', () => {
49
+ const statement = buffer.join('')
50
+ let rst = 0
51
+ let index = 0
52
+
53
+ if (!statement.length) {
54
+ console.error('Statement is empty.')
55
+ exit(1)
56
+ }
57
+
58
+ sql.connect(config, err => {
59
+ if (err) {
60
+ console.error(err.message)
61
+ exit(1)
62
+ }
63
+
64
+ write('[')
65
+
66
+ const request = new sql.Request()
67
+ request.stream = true
68
+ request.on('recordset', () => {
69
+ index = 0
70
+ if (rst++ > 0) {
71
+ write('],')
72
+ }
73
+
74
+ return write('[')
75
+ })
76
+
77
+ request.on('error', err => {
78
+ console.error(err.message)
79
+ sql.close()
80
+ return exit(1)
81
+ })
82
+
83
+ request.on('row', row => {
84
+ if (index++ > 0) {
85
+ write(',')
86
+ }
87
+
88
+ return write(JSON.stringify(row))
89
+ })
90
+
91
+ request.on('done', () => {
92
+ if (rst > 0) {
93
+ write(']')
94
+ }
95
+
96
+ write(']\n')
97
+ sql.close()
98
+ return exit(0)
99
+ })
100
+
101
+ request.query(statement)
102
+ })
103
+ })
104
+
105
+ process.on('uncaughtException', err => {
106
+ if (err.code === 'EPIPE') {
107
+ console.error('Failed to pipe output stream.')
108
+ } else {
109
+ console.error(err.message)
110
+ }
111
+
112
+ exit(1)
113
+ })
@@ -1,9 +1,9 @@
1
- 'use strict'
2
-
3
- module.exports = {
4
- READ_UNCOMMITTED: 0x01,
5
- READ_COMMITTED: 0x02,
6
- REPEATABLE_READ: 0x03,
7
- SERIALIZABLE: 0x04,
8
- SNAPSHOT: 0x05
9
- }
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ READ_UNCOMMITTED: 0x01,
5
+ READ_COMMITTED: 0x02,
6
+ REPEATABLE_READ: 0x03,
7
+ SERIALIZABLE: 0x04,
8
+ SNAPSHOT: 0x05
9
+ }
@@ -6,9 +6,11 @@ const BaseConnectionPool = require('../base/connection-pool')
6
6
  const { IDS, INCREMENT } = require('../utils')
7
7
  const shared = require('../shared')
8
8
  const ConnectionError = require('../error/connection-error')
9
+ const { platform } = require('os')
9
10
 
10
- const CONNECTION_STRING_PORT = 'Driver=SQL Server Native Client 11.0;Server=#{server},#{port};Database=#{database};Uid=#{user};Pwd=#{password};Trusted_Connection=#{trusted};Encrypt=#{encrypt};'
11
- const CONNECTION_STRING_NAMED_INSTANCE = 'Driver=SQL Server Native Client 11.0;Server=#{server}\\#{instance};Database=#{database};Uid=#{user};Pwd=#{password};Trusted_Connection=#{trusted};Encrypt=#{encrypt};'
11
+ const CONNECTION_DRIVER = ['darwin', 'linux'].includes(platform()) ? 'ODBC Driver 17 for SQL Server' : 'SQL Server Native Client 11.0'
12
+ const CONNECTION_STRING_PORT = `Driver=${CONNECTION_DRIVER};Server=#{server},#{port};Database=#{database};Uid=#{user};Pwd=#{password};Trusted_Connection=#{trusted};Encrypt=#{encrypt};`
13
+ const CONNECTION_STRING_NAMED_INSTANCE = `Driver=${CONNECTION_DRIVER};Server=#{server}\\#{instance};Database=#{database};Uid=#{user};Pwd=#{password};Trusted_Connection=#{trusted};Encrypt=#{encrypt};`
12
14
 
13
15
  class ConnectionPool extends BaseConnectionPool {
14
16
  _poolCreate () {
@@ -22,6 +22,13 @@ Object.defineProperty(module.exports, 'Promise', {
22
22
  }
23
23
  })
24
24
 
25
+ Object.defineProperty(module.exports, 'valueHandler', {
26
+ enumerable: true,
27
+ value: base.valueHandler,
28
+ writable: false,
29
+ configurable: false
30
+ })
31
+
25
32
  base.driver.name = 'msnodesqlv8'
26
33
  base.driver.ConnectionPool = ConnectionPool
27
34
  base.driver.Transaction = Transaction
@@ -8,6 +8,7 @@ const { IDS, objectHasProperty } = require('../utils')
8
8
  const { TYPES, DECLARATIONS, declare } = require('../datatypes')
9
9
  const { PARSERS: UDT } = require('../udt')
10
10
  const Table = require('../table')
11
+ const { valueHandler } = require('../shared')
11
12
 
12
13
  const JSON_COLUMN_ID = 'JSON_F52E2B61-18A1-11d1-B105-00805F49916B'
13
14
  const XML_COLUMN_ID = 'XML_F52E2B61-18A1-11d1-B105-00805F49916B'
@@ -122,7 +123,12 @@ const createColumns = function (metadata, arrayRowMode) {
122
123
  }
123
124
 
124
125
  const valueCorrection = function (value, metadata) {
125
- if ((metadata.sqlType === 'time') && (value != null)) {
126
+ const type = metadata && objectHasProperty(metadata, 'sqlType') && objectHasProperty(DECLARATIONS, metadata.sqlType)
127
+ ? DECLARATIONS[metadata.sqlType]
128
+ : null
129
+ if (type && valueHandler.has(type)) {
130
+ return valueHandler.get(type)(value)
131
+ } else if ((metadata.sqlType === 'time') && (value != null)) {
126
132
  value.setFullYear(1970)
127
133
  return value
128
134
  } else if ((metadata.sqlType === 'udt') && (value != null)) {
@@ -146,7 +152,11 @@ class Request extends BaseRequest {
146
152
  super._bulk(table, options, err => {
147
153
  if (err) return callback(err)
148
154
 
149
- table._makeBulk()
155
+ try {
156
+ table._makeBulk()
157
+ } catch (e) {
158
+ return callback(new RequestError(e, 'EREQUEST'))
159
+ }
150
160
 
151
161
  if (!table.name) {
152
162
  setImmediate(callback, new RequestError('Table name must be specified for bulk insert.', 'ENAME'))
package/lib/shared.js CHANGED
@@ -105,3 +105,10 @@ Object.defineProperty(module.exports, 'Promise', {
105
105
  PromiseLibrary = value
106
106
  }
107
107
  })
108
+
109
+ Object.defineProperty(module.exports, 'valueHandler', {
110
+ enumerable: true,
111
+ value: new Map(),
112
+ writable: false,
113
+ configurable: false
114
+ })
package/lib/table.js CHANGED
@@ -48,6 +48,13 @@ function Table (name) {
48
48
  }
49
49
  }
50
50
  )
51
+
52
+ Object.defineProperty(this.rows, 'clear', {
53
+ value () {
54
+ return this.splice(0, this.length)
55
+ }
56
+ }
57
+ )
51
58
  }
52
59
 
53
60
  /*
@@ -34,24 +34,23 @@ class ConnectionPool extends BaseConnectionPool {
34
34
  }, this.config.authentication)
35
35
  }
36
36
 
37
- cfg.options.database = this.config.database
38
- cfg.options.port = this.config.port
39
- cfg.options.connectTimeout = this.config.connectionTimeout || this.config.timeout || 15000
40
- cfg.options.requestTimeout = this.config.requestTimeout != null ? this.config.requestTimeout : 15000
37
+ cfg.options.database = cfg.options.database || this.config.database
38
+ cfg.options.port = cfg.options.port || this.config.port
39
+ cfg.options.connectTimeout = cfg.options.connectTimeout || this.config.connectionTimeout || this.config.timeout || 15000
40
+ cfg.options.requestTimeout = cfg.options.requestTimeout || this.config.requestTimeout != null ? this.config.requestTimeout : 15000
41
41
  cfg.options.tdsVersion = cfg.options.tdsVersion || '7_4'
42
- cfg.options.rowCollectionOnDone = false
43
- cfg.options.rowCollectionOnRequestCompletion = false
44
- cfg.options.useColumnNames = false
42
+ cfg.options.rowCollectionOnDone = cfg.options.rowCollectionOnDone || false
43
+ cfg.options.rowCollectionOnRequestCompletion = cfg.options.rowCollectionOnRequestCompletion || false
44
+ cfg.options.useColumnNames = cfg.options.useColumnNames || false
45
45
  cfg.options.appName = cfg.options.appName || 'node-mssql'
46
46
 
47
47
  // tedious always connect via tcp when port is specified
48
48
  if (cfg.options.instanceName) delete cfg.options.port
49
49
 
50
50
  if (isNaN(cfg.options.requestTimeout)) cfg.options.requestTimeout = 15000
51
- if (cfg.options.requestTimeout === Infinity) cfg.options.requestTimeout = 0
52
- if (cfg.options.requestTimeout < 0) cfg.options.requestTimeout = 0
51
+ if (cfg.options.requestTimeout === Infinity || cfg.options.requestTimeout < 0) cfg.options.requestTimeout = 0
53
52
 
54
- if (this.config.debug) {
53
+ if (!cfg.options.debug && this.config.debug) {
55
54
  cfg.options.debug = {
56
55
  packet: true,
57
56
  token: true,
@@ -73,6 +72,7 @@ class ConnectionPool extends BaseConnectionPool {
73
72
  }
74
73
 
75
74
  debug('connection(%d): established', IDS.get(tedious))
75
+ this.collation = tedious.databaseCollation
76
76
  resolveOnce(tedious)
77
77
  })
78
78
  IDS.add(tedious, 'Connection')
@@ -22,6 +22,13 @@ Object.defineProperty(module.exports, 'Promise', {
22
22
  }
23
23
  })
24
24
 
25
+ Object.defineProperty(module.exports, 'valueHandler', {
26
+ enumerable: true,
27
+ value: base.valueHandler,
28
+ writable: false,
29
+ configurable: false
30
+ })
31
+
25
32
  base.driver.name = 'tedious'
26
33
  base.driver.ConnectionPool = ConnectionPool
27
34
  base.driver.Transaction = Transaction
@@ -8,6 +8,7 @@ const { IDS, objectHasProperty } = require('../utils')
8
8
  const { TYPES, DECLARATIONS, declare, cast } = require('../datatypes')
9
9
  const Table = require('../table')
10
10
  const { PARSERS: UDT } = require('../udt')
11
+ const { valueHandler } = require('../shared')
11
12
 
12
13
  const JSON_COLUMN_ID = 'JSON_F52E2B61-18A1-11d1-B105-00805F49916B'
13
14
  const XML_COLUMN_ID = 'XML_F52E2B61-18A1-11d1-B105-00805F49916B'
@@ -159,7 +160,10 @@ const createColumns = function (metadata, arrayRowMode) {
159
160
  }
160
161
 
161
162
  const valueCorrection = function (value, metadata) {
162
- if ((metadata.type === tds.TYPES.UDT) && (value != null)) {
163
+ const type = getMssqlType(metadata.type)
164
+ if (valueHandler.has(type)) {
165
+ return valueHandler.get(type)(value)
166
+ } else if ((metadata.type === tds.TYPES.UDT) && (value != null)) {
163
167
  if (UDT[metadata.udtInfo.typeName]) {
164
168
  return UDT[metadata.udtInfo.typeName](value)
165
169
  } else {
@@ -213,7 +217,11 @@ class Request extends BaseRequest {
213
217
  super._bulk(table, options, err => {
214
218
  if (err) return callback(err)
215
219
 
216
- table._makeBulk()
220
+ try {
221
+ table._makeBulk()
222
+ } catch (e) {
223
+ return callback(new RequestError(e, 'EREQUEST'))
224
+ }
217
225
 
218
226
  if (!table.name) {
219
227
  return callback(new RequestError('Table name must be specified for bulk insert.', 'ENAME'))
@@ -330,26 +338,18 @@ class Request extends BaseRequest {
330
338
  bulk.addColumn(col.name, getTediousType(col.type), { nullable: col.nullable, length: col.length, scale: col.scale, precision: col.precision })
331
339
  }
332
340
 
333
- for (const row of table.rows) {
334
- try {
335
- bulk.addRow(row)
336
- } catch (e) {
337
- return handleError(true, connection, e)
338
- }
339
- }
340
-
341
341
  if (table.create) {
342
342
  const objectid = table.temporary ? `tempdb..[${table.name}]` : table.path
343
343
  const req = new tds.Request(`if object_id('${objectid.replace(/'/g, '\'\'')}') is null ${table.declare()}`, err => {
344
344
  if (err) return done(err)
345
345
 
346
- connection.execBulkLoad(bulk)
346
+ connection.execBulkLoad(bulk, table.rows)
347
347
  })
348
348
  this._setCurrentRequest(req)
349
349
 
350
350
  connection.execSqlBatch(req)
351
351
  } else {
352
- connection.execBulkLoad(bulk)
352
+ connection.execBulkLoad(bulk, table.rows)
353
353
  }
354
354
  })
355
355
  })
@@ -604,7 +604,7 @@ class Request extends BaseRequest {
604
604
  row.push(col.value)
605
605
  } else {
606
606
  const exi = row[col.metadata.colName]
607
- if (exi != null) {
607
+ if (exi !== undefined) {
608
608
  if (exi instanceof Array) {
609
609
  exi.push(col.value)
610
610
  } else {
@@ -641,7 +641,7 @@ class Request extends BaseRequest {
641
641
  const param = this.parameters[name]
642
642
 
643
643
  try {
644
- param.value = getTediousType(param.type).validate(param.value)
644
+ param.value = getTediousType(param.type).validate(param.value, this.parent.collation)
645
645
  } catch (e) {
646
646
  e.message = `Validation failed for parameter '${name}'. ${e.message}`
647
647
  const err = new RequestError(e, 'EPARAM')
package/package.json CHANGED
@@ -21,20 +21,20 @@
21
21
  "azure",
22
22
  "node-mssql"
23
23
  ],
24
- "version": "7.2.0",
24
+ "version": "8.0.1",
25
25
  "main": "index.js",
26
26
  "repository": "github:tediousjs/node-mssql",
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@tediousjs/connection-string": "^0.3.0",
30
- "debug": "^4",
30
+ "debug": "^4.3.3",
31
31
  "rfdc": "^1.3.0",
32
- "tarn": "^3.0.1",
33
- "tedious": "^11.0.7"
32
+ "tarn": "^3.0.2",
33
+ "tedious": "^14.0.0"
34
34
  },
35
35
  "devDependencies": {
36
- "mocha": "^8.3.2",
37
- "standard": "^16.0.3"
36
+ "mocha": "^9.1.3",
37
+ "standard": "^16.0.4"
38
38
  },
39
39
  "engines": {
40
40
  "node": ">=10"
package/test.js CHANGED
@@ -1,51 +1,40 @@
1
- 'use strict'
2
-
3
- const mssql = require('./')
4
-
5
- const sqlConfig = {
6
- password: 'Upper_l0wercase',
7
- database: 'di_production',
8
- stream: false,
9
- authentication: {
10
- type: 'test',
11
- },
12
- options: {
13
- trustServerCertificate: true,
14
- enableArithAbort: true,
15
- encrypt: true,
16
- abortTransactionOnError: false,
17
- },
18
- pool: {
19
- max: 1,
20
- min: 0,
21
- },
22
- port: 1433,
23
- user: 'sa',
24
- server: 'localhost',
25
- }
26
-
27
- async function main () {
28
- const pool = new mssql.ConnectionPool(sqlConfig)
29
- await pool.connect()
30
-
31
- const table = new mssql.Table('Sandbox.dbo.BulkTest')
32
- table.create = true
33
- table.columns.add('ABigInt', mssql.BigInt);
34
- table.rows.add(1.2)
35
-
36
- const transaction = new mssql.Transaction(pool);
37
- await transaction.begin();
38
-
39
- try {
40
- const request = new mssql.Request(transaction)
41
- await request.bulk(table)
42
- await transaction.commit();
43
- } catch (error) {
44
- console.error(error)
45
- await transaction.rollback();
46
- } finally {
47
- await pool.close();
48
- }
49
- }
50
-
51
- main().catch(console.error);
1
+ 'use strict'
2
+ const mssql = require('./')
3
+
4
+ const [, , max] = process.argv
5
+
6
+ const sqlConfig = {
7
+ password: 'P@ssw0rd',
8
+ database: 'test',
9
+ stream: false,
10
+ // driver: 'msnodesqlv8',
11
+ options: {
12
+ trustServerCertificate: true,
13
+ enableArithAbort: true,
14
+ encrypt: true,
15
+ abortTransactionOnError: false
16
+ },
17
+ pool: {
18
+ max: max ? parseInt(max) : 10,
19
+ min: 0
20
+ },
21
+ port: 1433,
22
+ user: 'sa',
23
+ server: 'localhost',
24
+ arrayRowMode: true
25
+ }
26
+
27
+ mssql.connect(sqlConfig).then((pool) => {
28
+ console.log('Connected to SQL server')
29
+ const request = pool.request()
30
+ request.stream = true
31
+ request.on('error', (err) => {
32
+ console.error('good', err)
33
+ })
34
+ return request.query('SELECT * FROM nontable')
35
+ }).catch((err) => {
36
+ console.error('bad', err)
37
+ }).then(() => {
38
+ console.log('Disconnecting from SQL server')
39
+ return mssql.close()
40
+ }).then(() => console.log('Disconnected'))