mssql-cr-layer 3.0.13 → 3.0.15

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +26 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mssql-cr-layer",
3
- "version": "3.0.13",
3
+ "version": "3.0.15",
4
4
  "description": "A MS SQL Server interface layer for common requests",
5
5
  "repository": "andrglo/mssql-cr-layer",
6
6
  "author": {
package/src/index.js CHANGED
@@ -5,6 +5,7 @@ const debug = require('debug')('layer:mssql')
5
5
  const scanMarkers = require('./scan-markers')
6
6
 
7
7
  const connectionParams = new WeakMap() // Hidden connection parameters
8
+ const rolledBack = new WeakMap() // transaction -> rolled back (by us or by the server)
8
9
 
9
10
  // Tag a DB error with the SQL + params that produced it, so error-alert
10
11
  // consumers can show what actually failed (drivers report code/number/state but
@@ -95,16 +96,8 @@ MssqlCrLayer.prototype.connect = function() {
95
96
  * @returns {Promise} With the return of the last promise executed
96
97
  */
97
98
  MssqlCrLayer.prototype.transaction = function(fn, options) {
98
- options = options || {}
99
- const isolationLevel = options.ISOLATION_LEVEL || this.ISOLATION_LEVEL
100
- return this.connect().then(function(connection) {
101
- const transaction = new mssql.Transaction(connection)
102
- let rolledBack = false
103
- transaction.on('rollback', function() {
104
- rolledBack = true
105
- })
106
- return transaction
107
- .begin(mssql.ISOLATION_LEVEL[isolationLevel])
99
+ return this.beginTransaction(options).then(function(transaction) {
100
+ return Promise.resolve()
108
101
  .then(function() {
109
102
  return fn(transaction)
110
103
  })
@@ -114,7 +107,7 @@ MssqlCrLayer.prototype.transaction = function(fn, options) {
114
107
  })
115
108
  })
116
109
  .catch(function(err) {
117
- if (!rolledBack) {
110
+ if (!rolledBack.get(transaction)) {
118
111
  return transaction.rollback().then(function() {
119
112
  throw err
120
113
  })
@@ -124,8 +117,6 @@ MssqlCrLayer.prototype.transaction = function(fn, options) {
124
117
  })
125
118
  }
126
119
 
127
- const rolledBack = new WeakMap()
128
-
129
120
  MssqlCrLayer.prototype.beginTransaction = function(options) {
130
121
  options = options || {}
131
122
  const isolationLevel = options.ISOLATION_LEVEL || this.ISOLATION_LEVEL
@@ -288,9 +279,29 @@ MssqlCrLayer.prototype.query = function(statement, params, options) {
288
279
  })
289
280
  })
290
281
  .catch(function(error) {
291
- return ps.unprepare().then(function() {
282
+ // The server rolled the transaction back while this statement ran
283
+ // (an error inside a trigger, XACT_ABORT, a trigger ROLLBACK):
284
+ // node-mssql has already handed the connection back to the pool,
285
+ // so it is no longer this statement's to unprepare on - another
286
+ // request may be using it, and the sp_unprepare would collide
287
+ // with it ("Requests can only be made in the LoggedIn state").
288
+ // `_aborted` is node-mssql's own flag, for a transaction this
289
+ // layer did not create.
290
+ if (
291
+ transaction &&
292
+ (rolledBack.get(transaction) || transaction._aborted === true)
293
+ ) {
292
294
  throw error
293
- })
295
+ }
296
+ // Never let a failed unprepare replace the statement's own error
297
+ return ps
298
+ .unprepare()
299
+ .catch(function(unprepareError) {
300
+ debug('unprepare failed %s %O', statement, unprepareError)
301
+ })
302
+ .then(function() {
303
+ throw error
304
+ })
294
305
  })
295
306
  })
296
307
  .catch(err => {