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

Commit 47e02c43 by Mick Hansen

fix(transaction): fix issue introduced in commit 7801903d where child transaction…

…s would not properly use a parent connection
1 parent 7801903d
...@@ -1705,8 +1705,8 @@ var QueryGenerator = { ...@@ -1705,8 +1705,8 @@ var QueryGenerator = {
* @param {Object} options An object with options. * @param {Object} options An object with options.
* @return {String} The generated sql query. * @return {String} The generated sql query.
*/ */
startTransactionQuery: function(transaction, options) { startTransactionQuery: function(transaction) {
if (options.parent) { if (transaction.parent) {
return 'SAVEPOINT ' + this.quoteIdentifier(transaction.name) + ';'; return 'SAVEPOINT ' + this.quoteIdentifier(transaction.name) + ';';
} }
...@@ -1732,8 +1732,8 @@ var QueryGenerator = { ...@@ -1732,8 +1732,8 @@ var QueryGenerator = {
* @param {Object} options An object with options. * @param {Object} options An object with options.
* @return {String} The generated sql query. * @return {String} The generated sql query.
*/ */
commitTransactionQuery: function(options) { commitTransactionQuery: function(transaction) {
if (options.parent) { if (transaction.parent) {
return; return;
} }
...@@ -1747,8 +1747,8 @@ var QueryGenerator = { ...@@ -1747,8 +1747,8 @@ var QueryGenerator = {
* @param {Object} options An object with options. * @param {Object} options An object with options.
* @return {String} The generated sql query. * @return {String} The generated sql query.
*/ */
rollbackTransactionQuery: function(transaction, options) { rollbackTransactionQuery: function(transaction) {
if (options.parent) { if (transaction.parent) {
return 'ROLLBACK TO SAVEPOINT ' + this.quoteIdentifier(transaction.name) + ';'; return 'ROLLBACK TO SAVEPOINT ' + this.quoteIdentifier(transaction.name) + ';';
} }
......
...@@ -1919,7 +1919,7 @@ Model.prototype.findOrCreate = function(options) { ...@@ -1919,7 +1919,7 @@ Model.prototype.findOrCreate = function(options) {
}); });
}).finally(function () { }).finally(function () {
if (internalTransaction && transaction) { if (internalTransaction && transaction) {
// If we created a transaction internally, we should clean it up // If we created a transaction internally (and not just a savepoint), we should clean it up
return transaction.commit(); return transaction.commit();
} }
}); });
......
...@@ -821,37 +821,44 @@ QueryInterface.prototype.setAutocommit = function(transaction, value, options) { ...@@ -821,37 +821,44 @@ QueryInterface.prototype.setAutocommit = function(transaction, value, options) {
if (!transaction || !(transaction instanceof Transaction)) { if (!transaction || !(transaction instanceof Transaction)) {
throw new Error('Unable to set autocommit for a transaction without transaction object!'); throw new Error('Unable to set autocommit for a transaction without transaction object!');
} }
if (transaction.parent) {
// Not possible to set a seperate isolation level for savepoints
return Promise.resolve();
}
options = _.assign({}, options || {}, { options = _.assign({}, options || {}, {
transaction: transaction, transaction: transaction.parent || transaction
parent: options.transaction
}); });
var sql = this.QueryGenerator.setAutocommitQuery(value, options); var sql = this.QueryGenerator.setAutocommitQuery(value, {
if (sql) { parent: transaction.parent
return this.sequelize.query(sql, options); });
} else {
return Promise.resolve(); if (!sql) return Promise.resolve();
}
return this.sequelize.query(sql, options);
}; };
QueryInterface.prototype.setIsolationLevel = function(transaction, value, options) { QueryInterface.prototype.setIsolationLevel = function(transaction, value, options) {
if (!transaction || !(transaction instanceof Transaction)) { if (!transaction || !(transaction instanceof Transaction)) {
throw new Error('Unable to set isolation level for a transaction without transaction object!'); throw new Error('Unable to set isolation level for a transaction without transaction object!');
} }
if (transaction.parent) {
// Not possible to set a seperate isolation level for savepoints
return Promise.resolve();
}
options = _.assign({}, options || {}, { options = _.assign({}, options || {}, {
transaction: transaction, transaction: transaction.parent || transaction
parent: options.transaction
}); });
var sql = this.QueryGenerator.setIsolationLevelQuery(value, options); var sql = this.QueryGenerator.setIsolationLevelQuery(value, {
parent: transaction.parent
});
if (sql) { if (!sql) return Promise.resolve();
return this.sequelize.query(sql, options);
} else { return this.sequelize.query(sql, options);
return Promise.resolve();
}
}; };
QueryInterface.prototype.startTransaction = function(transaction, options) { QueryInterface.prototype.startTransaction = function(transaction, options) {
...@@ -860,21 +867,22 @@ QueryInterface.prototype.startTransaction = function(transaction, options) { ...@@ -860,21 +867,22 @@ QueryInterface.prototype.startTransaction = function(transaction, options) {
} }
options = _.assign({}, options || {}, { options = _.assign({}, options || {}, {
transaction: transaction, transaction: transaction.parent || transaction
parent: options.transaction
}); });
var sql = this.QueryGenerator.startTransactionQuery(transaction, options); var sql = this.QueryGenerator.startTransactionQuery(transaction);
return this.sequelize.query(sql, options); return this.sequelize.query(sql, options);
}; };
QueryInterface.prototype.deferConstraints = function (transaction, options) { QueryInterface.prototype.deferConstraints = function (transaction, options) {
options = Utils._.extend({ options = Utils._.extend({
transaction: transaction, transaction: transaction.parent || transaction
parent: options.transaction
}, options || {}); }, options || {});
var sql = this.QueryGenerator.deferConstraintsQuery(options); var sql = this.QueryGenerator.deferConstraintsQuery({
parent: transaction.parent
});
if (sql) { if (sql) {
return this.sequelize.query(sql, options); return this.sequelize.query(sql, options);
...@@ -887,21 +895,19 @@ QueryInterface.prototype.commitTransaction = function(transaction, options) { ...@@ -887,21 +895,19 @@ QueryInterface.prototype.commitTransaction = function(transaction, options) {
if (!transaction || !(transaction instanceof Transaction)) { if (!transaction || !(transaction instanceof Transaction)) {
throw new Error('Unable to commit a transaction without transaction object!'); throw new Error('Unable to commit a transaction without transaction object!');
} }
if (transaction.parent) {
// Savepoints cannot be committed
return Promise.resolve();
}
options = _.assign({}, options || {}, { options = _.assign({}, options || {}, {
transaction: transaction, transaction: transaction.parent || transaction,
parent: options.transaction,
supportsSearchPath: false supportsSearchPath: false
}); });
var sql = this.QueryGenerator.commitTransactionQuery(options); var sql = this.QueryGenerator.commitTransactionQuery(transaction);
if (sql) { return this.sequelize.query(sql, options);
return this.sequelize.query(sql, options);
} else {
return Promise.resolve();
}
}; };
QueryInterface.prototype.rollbackTransaction = function(transaction, options) { QueryInterface.prototype.rollbackTransaction = function(transaction, options) {
...@@ -910,12 +916,12 @@ QueryInterface.prototype.rollbackTransaction = function(transaction, options) { ...@@ -910,12 +916,12 @@ QueryInterface.prototype.rollbackTransaction = function(transaction, options) {
} }
options = _.assign({}, options || {}, { options = _.assign({}, options || {}, {
transaction: transaction, transaction: transaction.parent || transaction,
parent: options.transaction,
supportsSearchPath: false supportsSearchPath: false
}); });
var sql = this.QueryGenerator.rollbackTransactionQuery(transaction, options); var sql = this.QueryGenerator.rollbackTransactionQuery(transaction);
return this.sequelize.query(sql, options); return this.sequelize.query(sql, options);
}; };
......
...@@ -789,6 +789,7 @@ Sequelize.prototype.query = function(sql, options) { ...@@ -789,6 +789,7 @@ Sequelize.prototype.query = function(sql, options) {
return Promise.resolve( return Promise.resolve(
options.transaction ? options.transaction.connection : self.connectionManager.getConnection(options) options.transaction ? options.transaction.connection : self.connectionManager.getConnection(options)
).then(function (connection) { ).then(function (connection) {
var query = new self.dialect.Query(connection, self, options); var query = new self.dialect.Query(connection, self, options);
return query.run(sql, bindParameters).finally(function() { return query.run(sql, bindParameters).finally(function() {
if (options.transaction) return; if (options.transaction) return;
......
...@@ -23,13 +23,14 @@ var Transaction = module.exports = function(sequelize, options) { ...@@ -23,13 +23,14 @@ var Transaction = module.exports = function(sequelize, options) {
autocommit: true, autocommit: true,
isolationLevel: sequelize.options.isolationLevel isolationLevel: sequelize.options.isolationLevel
}, options || {}); }, options || {});
this.id = this.options.transaction ? this.options.transaction.id : uuid.v4();
if (this.options.transaction) { this.parent = this.options.transaction
this.id = this.options.transaction.id; this.id = this.parent ? this.parent.id : uuid.v4();
this.options.transaction.savepoints.push(this);
this.name = this.id + '-savepoint-' + this.options.transaction.savepoints.length; if (this.parent) {
this.parent = this.options.transaction; this.id = this.parent.id;
this.parent.savepoints.push(this);
this.name = this.id + '-savepoint-' + this.parent.savepoints.length;
} else { } else {
this.id = this.name = uuid.v4(); this.id = this.name = uuid.v4();
} }
...@@ -178,7 +179,7 @@ Transaction.prototype.prepareEnvironment = function() { ...@@ -178,7 +179,7 @@ Transaction.prototype.prepareEnvironment = function() {
var self = this; var self = this;
return Utils.Promise.resolve( return Utils.Promise.resolve(
self.options.transaction ? self.options.transaction.connection : self.sequelize.connectionManager.getConnection({ uuid: self.id }) self.parent ? self.parent.connection : self.sequelize.connectionManager.getConnection({ uuid: self.id })
).then(function (connection) { ).then(function (connection) {
self.connection = connection; self.connection = connection;
self.connection.uuid = self.id; self.connection.uuid = self.id;
......
{ {
"name": "sequelize", "name": "sequelize",
"description": "Multi dialect ORM for Node.JS/io.js", "description": "Multi dialect ORM for Node.JS/io.js",
"version": "3.14.0", "version": "3.14.1",
"author": "Sascha Depold <sascha@depold.com>", "author": "Sascha Depold <sascha@depold.com>",
"contributors": [ "contributors": [
{ {
......
...@@ -45,9 +45,17 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -45,9 +45,17 @@ describe(Support.getTestDialectTeaser('Model'), function() {
it('supports transactions', function() { it('supports transactions', function() {
var self = this; var self = this;
return this.sequelize.transaction().then(function(t) { return this.sequelize.transaction().then(function(t) {
return self.User.findOrCreate({ where: { username: 'Username' }, defaults: { data: 'some data' }, transaction: t }).then(function() { return self.User.findOrCreate({
where: {
username: 'Username'
},
defaults: {
data: 'some data'
},
transaction: t
}).then(function() {
return self.User.count().then(function(count) { return self.User.count().then(function(count) {
expect(count).to.equal(0); expect(count).to.equal(0);
return t.commit().then(function() { return t.commit().then(function() {
return self.User.count().then(function(count) { return self.User.count().then(function(count) {
expect(count).to.equal(1); expect(count).to.equal(1);
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!