不要怂,就是干,撸起袖子干!

Commit 7801903d by Mick Hansen

fix(transaction): Issue with transaction options leaking and certain queries run…

…ning outside of the transaction connection.
1 parent 7057a7c9
# 3.14.1
- [FIXED] Issue with transaction options leaking and certain queries running outside of the transaction connection.
# 3.14.0
- [FIXED] Apply scopes to `aggregate` [#4764](https://github.com/sequelize/sequelize/issues/4764)
- [FIXED] Improved postgres enum schema handling [#4796](https://github.com/sequelize/sequelize/issues/4796)
......
......@@ -822,13 +822,14 @@ QueryInterface.prototype.setAutocommit = function(transaction, value, options) {
throw new Error('Unable to set autocommit for a transaction without transaction object!');
}
options = Utils._.extend({
options = _.assign({}, options || {}, {
transaction: transaction,
parent: options.transaction
}, options || {});
});
var sql = this.QueryGenerator.setAutocommitQuery(value, options);
if (sql) {
return this.sequelize.query(sql, { transaction: transaction, logging: options.logging });
return this.sequelize.query(sql, options);
} else {
return Promise.resolve();
}
......@@ -839,14 +840,15 @@ QueryInterface.prototype.setIsolationLevel = function(transaction, value, option
throw new Error('Unable to set isolation level for a transaction without transaction object!');
}
options = Utils._.extend({
options = _.assign({}, options || {}, {
transaction: transaction,
parent: options.transaction
}, options || {});
});
var sql = this.QueryGenerator.setIsolationLevelQuery(value, options);
if (sql) {
return this.sequelize.query(sql, { transaction: transaction, logging: options.logging });
return this.sequelize.query(sql, options);
} else {
return Promise.resolve();
}
......@@ -857,10 +859,10 @@ QueryInterface.prototype.startTransaction = function(transaction, options) {
throw new Error('Unable to start a transaction without transaction object!');
}
options = Utils._.extend({
options = _.assign({}, options || {}, {
transaction: transaction,
parent: options.transaction
}, options || {});
});
var sql = this.QueryGenerator.startTransactionQuery(transaction, options);
return this.sequelize.query(sql, options);
......@@ -886,11 +888,12 @@ QueryInterface.prototype.commitTransaction = function(transaction, options) {
throw new Error('Unable to commit a transaction without transaction object!');
}
options = Utils._.extend({
options = _.assign({}, options || {}, {
transaction: transaction,
parent: options.transaction,
supportsSearchPath: false
}, options || {});
});
var sql = this.QueryGenerator.commitTransactionQuery(options);
......@@ -906,11 +909,11 @@ QueryInterface.prototype.rollbackTransaction = function(transaction, options) {
throw new Error('Unable to rollback a transaction without transaction object!');
}
options = Utils._.extend({
options = _.assign({}, options || {}, {
transaction: transaction,
parent: options.transaction,
supportsSearchPath: false
}, options || {});
});
var sql = this.QueryGenerator.rollbackTransactionQuery(transaction, options);
return this.sequelize.query(sql, options);
......
......@@ -33,6 +33,8 @@ var Transaction = module.exports = function(sequelize, options) {
} else {
this.id = this.name = uuid.v4();
}
delete this.options.transaction;
};
/**
......
......@@ -13,6 +13,14 @@ var chai = require('chai')
if (current.dialect.supports.transactions) {
describe(Support.getTestDialectTeaser('Transaction'), function() {
beforeEach(function () {
this.sinon = sinon.sandbox.create();
});
afterEach(function () {
this.sinon.restore();
});
this.timeout(5000);
describe('constructor', function() {
it('stores options', function() {
......@@ -126,7 +134,7 @@ describe(Support.getTestDialectTeaser('Transaction'), function() {
return expect(
this.sequelize.transaction().then(function(t) {
return self.sequelize.query('SELECT 1+1', {transaction: t, raw: true}).then(function() {
return t.commit();
return t.rollback();
}).then(function() {
return self.sequelize.query('SELECT 1+1', {transaction: t, raw: true});
});
......@@ -170,6 +178,38 @@ describe(Support.getTestDialectTeaser('Transaction'), function() {
})).to.be.rejectedWith('Error: Transaction cannot be rolled back because it has been finished with state: rollback');
});
it('works even if a transaction: null option is passed', function () {
this.sinon.spy(this.sequelize, 'query');
return this.sequelize.transaction({
transaction: null
}).bind(this).then(function (t) {
return t.commit().bind(this).then(function () {
expect(this.sequelize.query.callCount).to.be.greaterThan(0);
for (var i = 0; i < this.sequelize.query.callCount; i++) {
expect(this.sequelize.query.getCall(i).args[1].transaction).to.equal(t);
}
});
});
});
it('works even if a transaction: undefined option is passed', function () {
this.sinon.spy(this.sequelize, 'query');
return this.sequelize.transaction({
transaction: undefined
}).bind(this).then(function (t) {
return t.commit().bind(this).then(function () {
expect(this.sequelize.query.callCount).to.be.greaterThan(0);
for (var i = 0; i < this.sequelize.query.callCount; i++) {
expect(this.sequelize.query.getCall(i).args[1].transaction).to.equal(t);
}
});
});
});
if (dialect === 'sqlite'){
it('provides persistent transactions', function () {
var sequelize = new Support.Sequelize('database', 'username', 'password', {dialect: 'sqlite'})
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!