From 0d0aad6a5dea554e4d853e438b35d4b334928de9 Mon Sep 17 00:00:00 2001 From: Jozef Hartinger Date: Mon, 15 Feb 2016 21:08:11 +0100 Subject: [PATCH] Log which query tried to run on a finished transaction The "commit has been called on this transaction" error message usually indicates a problem with chaining of query promises within a transaction block. In more complex transaction blocks it may not be immediately clear which query is improperly chained and the current error message does not help much. This change attaches the rejected query (SQL) as the 'sql' property of the error. This makes it easier to identify a problem in an application. --- lib/sequelize.js | 4 +++- test/integration/transaction.test.js | 34 +++++++++++++++++++--------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/sequelize.js b/lib/sequelize.js index ab321108cdb6..e2566b4aed04 100755 --- a/lib/sequelize.js +++ b/lib/sequelize.js @@ -789,7 +789,9 @@ Sequelize.prototype.query = function(sql, options) { } if (options.transaction && options.transaction.finished) { - return Promise.reject(new Error(options.transaction.finished+' has been called on this transaction('+options.transaction.id+'), you can no longer use it')); + var error = new Error(options.transaction.finished+' has been called on this transaction('+options.transaction.id+'), you can no longer use it. (The rejected query is attached as the \'sql\' property of this error)'); + error.sql = sql; + return Promise.reject(error); } if (this.test.$trackRunningQueries) { diff --git a/test/integration/transaction.test.js b/test/integration/transaction.test.js index a67de5d7683f..cb0bb1340596 100644 --- a/test/integration/transaction.test.js +++ b/test/integration/transaction.test.js @@ -117,15 +117,17 @@ describe(Support.getTestDialectTeaser('Transaction'), function() { it('does not allow queries after commit', function() { var self = this; - return expect( - this.sequelize.transaction().then(function(t) { - return self.sequelize.query('SELECT 1+1', {transaction: t, raw: true}).then(function() { - return t.commit(); - }).then(function() { - return self.sequelize.query('SELECT 1+1', {transaction: t, raw: true}); - }); - }) - ).to.eventually.be.rejected; + return this.sequelize.transaction().then(function(t) { + return self.sequelize.query('SELECT 1+1', {transaction: t, raw: true}).then(function() { + return t.commit(); + }).then(function() { + return self.sequelize.query('SELECT 1+1', {transaction: t, raw: true}); + }); + }).throw(new Error('Expected error not thrown')) + .catch (function (err) { + expect (err.message).to.match(/commit has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/); + expect (err.sql).to.equal('SELECT 1+1'); + }); }); it('does not allow queries immediatly after commit call', function() { @@ -135,7 +137,12 @@ describe(Support.getTestDialectTeaser('Transaction'), function() { return self.sequelize.query('SELECT 1+1', {transaction: t, raw: true}).then(function() { return Promise.join( expect(t.commit()).to.eventually.be.fulfilled, - expect(self.sequelize.query('SELECT 1+1', {transaction: t, raw: true})).to.eventually.be.rejectedWith(/commit has been called on this transaction\([^)]+\), you can no longer use it/) + self.sequelize.query('SELECT 1+1', {transaction: t, raw: true}) + .throw(new Error('Expected error not thrown')) + .catch (function (err) { + expect (err.message).to.match(/commit has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/); + expect (err.sql).to.equal('SELECT 1+1'); + }) ); }); }) @@ -161,7 +168,12 @@ describe(Support.getTestDialectTeaser('Transaction'), function() { this.sequelize.transaction().then(function(t) { return Promise.join( expect(t.rollback()).to.eventually.be.fulfilled, - expect(self.sequelize.query('SELECT 1+1', {transaction: t, raw: true})).to.eventually.be.rejectedWith(/rollback has been called on this transaction\([^)]+\), you can no longer use it/) + self.sequelize.query('SELECT 1+1', {transaction: t, raw: true}) + .throw(new Error('Expected error not thrown')) + .catch (function (err) { + expect (err.message).to.match(/rollback has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/); + expect (err.sql).to.equal('SELECT 1+1'); + }) ); }) ).to.eventually.be.fulfilled;