mssql 12.3.0 → 12.4.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/README.md +189 -14
- package/lib/base/connection-pool.js +61 -10
- package/lib/base/index.js +2 -0
- package/lib/base/prepared-statement.js +62 -14
- package/lib/base/request.js +137 -65
- package/lib/base/transaction.js +32 -1
- package/lib/diagnostics.js +153 -0
- package/lib/msnodesqlv8/connection-pool.js +15 -2
- package/lib/tedious/connection-pool.js +13 -0
- package/lib/tedious/request.js +55 -25
- package/lib/tedious/transaction.js +5 -0
- package/lib/udt.js +25 -23
- package/lib/utils.js +10 -1
- package/package.json +2 -2
package/lib/tedious/request.js
CHANGED
|
@@ -200,9 +200,13 @@ const parameterCorrection = function (value) {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
for (const col of value.columns) {
|
|
203
|
+
const tediousType = getTediousType(col.type)
|
|
204
|
+
if (tediousType === tds.TYPES.Variant) {
|
|
205
|
+
throw new RequestError(`Column '${col.name}' in TVP '${value.schema ? value.schema + '.' : ''}${value.name}' uses sql_variant which is not supported by the tedious driver for TVP column types. Consider using a more specific data type.`, 'EARGS')
|
|
206
|
+
}
|
|
203
207
|
tvp.columns.push({
|
|
204
208
|
name: col.name,
|
|
205
|
-
type:
|
|
209
|
+
type: tediousType,
|
|
206
210
|
length: col.length,
|
|
207
211
|
scale: col.scale,
|
|
208
212
|
precision: col.precision
|
|
@@ -664,9 +668,18 @@ class Request extends BaseRequest {
|
|
|
664
668
|
} catch (e) {
|
|
665
669
|
e.message = `Validation failed for parameter '${name}'. ${e.message}`
|
|
666
670
|
const err = new RequestError(e, 'EPARAM')
|
|
671
|
+
delete this._cancel
|
|
672
|
+
|
|
673
|
+
if (!hasReturned) {
|
|
674
|
+
for (const event in errorHandlers) {
|
|
675
|
+
connection.removeListener(event, errorHandlers[event])
|
|
676
|
+
}
|
|
667
677
|
|
|
668
|
-
|
|
669
|
-
|
|
678
|
+
this.parent.release(connection)
|
|
679
|
+
hasReturned = true
|
|
680
|
+
return callback(err)
|
|
681
|
+
}
|
|
682
|
+
return
|
|
670
683
|
}
|
|
671
684
|
}
|
|
672
685
|
|
|
@@ -703,21 +716,23 @@ class Request extends BaseRequest {
|
|
|
703
716
|
|
|
704
717
|
req.sqlTextOrProcedure = `declare ${declarations.join(', ')};select ${assigns.join(', ')};${req.sqlTextOrProcedure};${batchHasOutput ? (`select 1 as [___return___], ${selects.join(', ')}`) : ''}`
|
|
705
718
|
}
|
|
706
|
-
} else {
|
|
707
|
-
for (const name in this.parameters) {
|
|
708
|
-
if (!objectHasProperty(this.parameters, name)) {
|
|
709
|
-
continue
|
|
710
|
-
}
|
|
711
|
-
const param = this.parameters[name]
|
|
712
|
-
if (param.io === 1) {
|
|
713
|
-
req.addParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { length: param.length, scale: param.scale, precision: param.precision })
|
|
714
|
-
} else {
|
|
715
|
-
req.addOutputParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { length: param.length, scale: param.scale, precision: param.precision })
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
719
|
}
|
|
719
720
|
|
|
720
721
|
try {
|
|
722
|
+
if (!this._isBatch) {
|
|
723
|
+
for (const name in this.parameters) {
|
|
724
|
+
if (!objectHasProperty(this.parameters, name)) {
|
|
725
|
+
continue
|
|
726
|
+
}
|
|
727
|
+
const param = this.parameters[name]
|
|
728
|
+
if (param.io === 1) {
|
|
729
|
+
req.addParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { length: param.length, scale: param.scale, precision: param.precision })
|
|
730
|
+
} else {
|
|
731
|
+
req.addOutputParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { length: param.length, scale: param.scale, precision: param.precision })
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
721
736
|
connection[this._isBatch ? 'execSqlBatch' : 'execSql'](req)
|
|
722
737
|
} catch (error) {
|
|
723
738
|
handleError(true, connection, error)
|
|
@@ -983,19 +998,34 @@ class Request extends BaseRequest {
|
|
|
983
998
|
output[parameterName] = value
|
|
984
999
|
})
|
|
985
1000
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1001
|
+
try {
|
|
1002
|
+
for (const name in this.parameters) {
|
|
1003
|
+
if (!objectHasProperty(this.parameters, name)) {
|
|
1004
|
+
continue
|
|
1005
|
+
}
|
|
1006
|
+
const param = this.parameters[name]
|
|
1007
|
+
if (param.io === 1) {
|
|
1008
|
+
req.addParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { length: param.length, scale: param.scale, precision: param.precision })
|
|
1009
|
+
} else {
|
|
1010
|
+
req.addOutputParameter(param.name, getTediousType(param.type), parameterCorrection(param.value), { length: param.length, scale: param.scale, precision: param.precision })
|
|
1011
|
+
}
|
|
989
1012
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1013
|
+
|
|
1014
|
+
connection.callProcedure(req)
|
|
1015
|
+
} catch (error) {
|
|
1016
|
+
const err = error instanceof RequestError ? error : new RequestError(error, 'EREQUEST')
|
|
1017
|
+
delete this._cancel
|
|
1018
|
+
|
|
1019
|
+
if (!hasReturned) {
|
|
1020
|
+
for (const event in errorHandlers) {
|
|
1021
|
+
connection.removeListener(event, errorHandlers[event])
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
this.parent.release(connection)
|
|
1025
|
+
hasReturned = true
|
|
1026
|
+
callback(err)
|
|
995
1027
|
}
|
|
996
1028
|
}
|
|
997
|
-
|
|
998
|
-
connection.callProcedure(req)
|
|
999
1029
|
})
|
|
1000
1030
|
})
|
|
1001
1031
|
}
|
|
@@ -4,6 +4,7 @@ const debug = require('debug')('mssql:tedi')
|
|
|
4
4
|
const BaseTransaction = require('../base/transaction')
|
|
5
5
|
const { IDS } = require('../utils')
|
|
6
6
|
const TransactionError = require('../error/transaction-error')
|
|
7
|
+
const { CHANNELS, publish } = require('../diagnostics')
|
|
7
8
|
|
|
8
9
|
class Transaction extends BaseTransaction {
|
|
9
10
|
constructor (parent) {
|
|
@@ -23,6 +24,10 @@ class Transaction extends BaseTransaction {
|
|
|
23
24
|
this._acquiredConfig = null
|
|
24
25
|
this._aborted = true
|
|
25
26
|
|
|
27
|
+
publish(CHANNELS.TRANSACTION_ROLLBACK, () => ({
|
|
28
|
+
transactionId: IDS.get(this),
|
|
29
|
+
aborted: true
|
|
30
|
+
}))
|
|
26
31
|
this.emit('rollback', true)
|
|
27
32
|
}
|
|
28
33
|
}
|
package/lib/udt.js
CHANGED
|
@@ -44,6 +44,12 @@ const SEGMENT = {
|
|
|
44
44
|
FIRST_ARC: 0x03
|
|
45
45
|
}; */
|
|
46
46
|
|
|
47
|
+
const ensureBytes = (buffer, needed) => {
|
|
48
|
+
if (buffer.position + needed > buffer.length) {
|
|
49
|
+
throw new Error(`Corrupt or truncated spatial data: expected ${needed} bytes at position ${buffer.position}, but only ${buffer.length - buffer.position} bytes remain`)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
class Point {
|
|
48
54
|
constructor () {
|
|
49
55
|
this.x = 0
|
|
@@ -64,6 +70,8 @@ const parsePoints = (buffer, count, isGeometryPoint) => {
|
|
|
64
70
|
return points
|
|
65
71
|
}
|
|
66
72
|
|
|
73
|
+
ensureBytes(buffer, count * 16)
|
|
74
|
+
|
|
67
75
|
if (isGeometryPoint) {
|
|
68
76
|
// GEOMETRY POINT (s2.1.6): x then y.
|
|
69
77
|
for (let i = 1; i <= count; i++) {
|
|
@@ -101,6 +109,8 @@ const parseZ = (buffer, points) => {
|
|
|
101
109
|
return
|
|
102
110
|
}
|
|
103
111
|
|
|
112
|
+
ensureBytes(buffer, points.length * 8)
|
|
113
|
+
|
|
104
114
|
points.forEach(point => {
|
|
105
115
|
point.z = buffer.readDoubleLE(buffer.position)
|
|
106
116
|
buffer.position += 8
|
|
@@ -114,6 +124,8 @@ const parseM = (buffer, points) => {
|
|
|
114
124
|
return
|
|
115
125
|
}
|
|
116
126
|
|
|
127
|
+
ensureBytes(buffer, points.length * 8)
|
|
128
|
+
|
|
117
129
|
points.forEach(point => {
|
|
118
130
|
point.m = buffer.readDoubleLE(buffer.position)
|
|
119
131
|
buffer.position += 8
|
|
@@ -139,6 +151,8 @@ const parseFigures = (buffer, count, properties) => {
|
|
|
139
151
|
pointOffset: 0
|
|
140
152
|
})
|
|
141
153
|
} else {
|
|
154
|
+
ensureBytes(buffer, count * 5)
|
|
155
|
+
|
|
142
156
|
for (let i = 1; i <= count; i++) {
|
|
143
157
|
figures.push({
|
|
144
158
|
attribute: buffer.readUInt8(buffer.position),
|
|
@@ -173,6 +187,8 @@ const parseShapes = (buffer, count, properties) => {
|
|
|
173
187
|
type: 0x02
|
|
174
188
|
})
|
|
175
189
|
} else {
|
|
190
|
+
ensureBytes(buffer, count * 9)
|
|
191
|
+
|
|
176
192
|
for (let i = 1; i <= count; i++) {
|
|
177
193
|
shapes.push({
|
|
178
194
|
parentOffset: buffer.readInt32LE(buffer.position),
|
|
@@ -195,6 +211,8 @@ const parseSegments = (buffer, count) => {
|
|
|
195
211
|
return segments
|
|
196
212
|
}
|
|
197
213
|
|
|
214
|
+
ensureBytes(buffer, count)
|
|
215
|
+
|
|
198
216
|
for (let i = 1; i <= count; i++) {
|
|
199
217
|
segments.push({ type: buffer.readUInt8(buffer.position) })
|
|
200
218
|
|
|
@@ -207,6 +225,8 @@ const parseSegments = (buffer, count) => {
|
|
|
207
225
|
const parseGeography = (buffer, isUsingGeometryPoints) => {
|
|
208
226
|
// s2.1.1 + s.2.1.2
|
|
209
227
|
|
|
228
|
+
ensureBytes(buffer, 6)
|
|
229
|
+
|
|
210
230
|
const srid = buffer.readInt32LE(0)
|
|
211
231
|
if (srid === -1) {
|
|
212
232
|
return null
|
|
@@ -220,9 +240,6 @@ const parseGeography = (buffer, isUsingGeometryPoints) => {
|
|
|
220
240
|
const flags = buffer.readUInt8(5)
|
|
221
241
|
buffer.position = 6
|
|
222
242
|
|
|
223
|
-
// console.log("srid", srid)
|
|
224
|
-
// console.log("version", version)
|
|
225
|
-
|
|
226
243
|
const properties = {
|
|
227
244
|
Z: (flags & (1 << 0)) > 0,
|
|
228
245
|
M: (flags & (1 << 1)) > 0,
|
|
@@ -232,23 +249,20 @@ const parseGeography = (buffer, isUsingGeometryPoints) => {
|
|
|
232
249
|
}
|
|
233
250
|
|
|
234
251
|
if (value.version === 2) {
|
|
235
|
-
properties.H = (flags & (1 <<
|
|
252
|
+
properties.H = (flags & (1 << 5)) > 0
|
|
236
253
|
}
|
|
237
254
|
|
|
238
|
-
// console.log("properties", properties);
|
|
239
|
-
|
|
240
255
|
let numberOfPoints
|
|
241
256
|
if (properties.P) {
|
|
242
257
|
numberOfPoints = 1
|
|
243
258
|
} else if (properties.L) {
|
|
244
259
|
numberOfPoints = 2
|
|
245
260
|
} else {
|
|
261
|
+
ensureBytes(buffer, 4)
|
|
246
262
|
numberOfPoints = buffer.readUInt32LE(buffer.position)
|
|
247
263
|
buffer.position += 4
|
|
248
264
|
}
|
|
249
265
|
|
|
250
|
-
// console.log("numberOfPoints", numberOfPoints)
|
|
251
|
-
|
|
252
266
|
value.points = parsePoints(buffer, numberOfPoints, isUsingGeometryPoints)
|
|
253
267
|
|
|
254
268
|
if (properties.Z) {
|
|
@@ -259,49 +273,37 @@ const parseGeography = (buffer, isUsingGeometryPoints) => {
|
|
|
259
273
|
parseM(buffer, value.points)
|
|
260
274
|
}
|
|
261
275
|
|
|
262
|
-
// console.log("points", points)
|
|
263
|
-
|
|
264
276
|
let numberOfFigures
|
|
265
277
|
if (properties.P) {
|
|
266
278
|
numberOfFigures = 1
|
|
267
279
|
} else if (properties.L) {
|
|
268
280
|
numberOfFigures = 1
|
|
269
281
|
} else {
|
|
282
|
+
ensureBytes(buffer, 4)
|
|
270
283
|
numberOfFigures = buffer.readUInt32LE(buffer.position)
|
|
271
284
|
buffer.position += 4
|
|
272
285
|
}
|
|
273
286
|
|
|
274
|
-
// console.log("numberOfFigures", numberOfFigures)
|
|
275
|
-
|
|
276
287
|
value.figures = parseFigures(buffer, numberOfFigures, properties)
|
|
277
288
|
|
|
278
|
-
// console.log("figures", figures)
|
|
279
|
-
|
|
280
289
|
let numberOfShapes
|
|
281
290
|
if (properties.P) {
|
|
282
291
|
numberOfShapes = 1
|
|
283
292
|
} else if (properties.L) {
|
|
284
293
|
numberOfShapes = 1
|
|
285
294
|
} else {
|
|
295
|
+
ensureBytes(buffer, 4)
|
|
286
296
|
numberOfShapes = buffer.readUInt32LE(buffer.position)
|
|
287
297
|
buffer.position += 4
|
|
288
298
|
}
|
|
289
299
|
|
|
290
|
-
// console.log("numberOfShapes", numberOfShapes)
|
|
291
|
-
|
|
292
300
|
value.shapes = parseShapes(buffer, numberOfShapes, properties)
|
|
293
301
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
if (value.version === 2 && buffer.position < buffer.length) {
|
|
302
|
+
if (value.version === 2 && buffer.position + 4 <= buffer.length) {
|
|
297
303
|
const numberOfSegments = buffer.readUInt32LE(buffer.position)
|
|
298
304
|
buffer.position += 4
|
|
299
305
|
|
|
300
|
-
// console.log("numberOfSegments", numberOfSegments)
|
|
301
|
-
|
|
302
306
|
value.segments = parseSegments(buffer, numberOfSegments)
|
|
303
|
-
|
|
304
|
-
// console.log("segments", segments)
|
|
305
307
|
} else {
|
|
306
308
|
value.segments = []
|
|
307
309
|
}
|
package/lib/utils.js
CHANGED
|
@@ -9,6 +9,14 @@ const INCREMENT = {
|
|
|
9
9
|
PreparedStatement: 1
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
const getPoolId = (obj) => {
|
|
13
|
+
let parent = obj && obj.parent
|
|
14
|
+
while (parent && !parent.pool) {
|
|
15
|
+
parent = parent.parent
|
|
16
|
+
}
|
|
17
|
+
return parent ? IDS.get(parent) : undefined
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
module.exports = {
|
|
13
21
|
objectHasProperty: (object, property) => Object.prototype.hasOwnProperty.call(object, property),
|
|
14
22
|
INCREMENT,
|
|
@@ -18,5 +26,6 @@ module.exports = {
|
|
|
18
26
|
if (id) return IDS.set(object, id)
|
|
19
27
|
IDS.set(object, INCREMENT[type]++)
|
|
20
28
|
}
|
|
21
|
-
}
|
|
29
|
+
},
|
|
30
|
+
getPoolId
|
|
22
31
|
}
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"azure",
|
|
22
22
|
"node-mssql"
|
|
23
23
|
],
|
|
24
|
-
"version": "12.
|
|
24
|
+
"version": "12.4.0",
|
|
25
25
|
"main": "index.js",
|
|
26
26
|
"type": "commonjs",
|
|
27
27
|
"repository": {
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"standard": "^17.0.0"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
|
-
"node": ">=18"
|
|
55
|
+
"node": ">=18.19.0"
|
|
56
56
|
},
|
|
57
57
|
"files": [
|
|
58
58
|
"lib/",
|