Skip to content

Commit 14b93f7

Browse files
committed
Merge pull request mysqljs#586 from jflitton/master
Basic transaction support for connections
2 parents bebd8e4 + 3b15c90 commit 14b93f7

File tree

4 files changed

+118
-57
lines changed

4 files changed

+118
-57
lines changed

Readme.md

+39-1
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,45 @@ connection.query(options, function(err, results) {
701701
});
702702
```
703703

704+
## Transactions
705+
706+
Simple transaction support is available at the connection level:
707+
708+
```js
709+
connection.beginTransaction(function(err) {
710+
if (err) { throw err; }
711+
connection.query('INSERT INTO posts SET title=?', title, function(err, result) {
712+
if (err) {
713+
connection.rollback(function() {
714+
throw err;
715+
});
716+
}
717+
718+
var log = 'Post ' + result.insertId + ' added';
719+
720+
connection.query('INSERT INTO log SET data=?', log, function(err, result) {
721+
if (err) {
722+
connection.rollback(function() {
723+
throw err;
724+
});
725+
}
726+
connection.commit(function(err) {
727+
if (err) {
728+
connection.rollback(function() {
729+
throw err;
730+
});
731+
}
732+
console.log('success!');
733+
});
734+
});
735+
});
736+
});
737+
```
738+
Please note that beginTransaction(), commit() and rollback() are simply convenience
739+
functions that execute the START TRANSACTION, COMMIT, and ROLLBACK commands respectively.
740+
It is important to understand that many commands in MySQL can cause an implicit commit,
741+
as described [in the MySQL documentation](http://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html)
742+
704743
## Error handling
705744

706745
This module comes with a consistent approach to error handling that you should
@@ -973,4 +1012,3 @@ For example, if you have an installation of mysql running on localhost:3306 and
9731012
* Prepared statements
9741013
* setTimeout() for Connection / Query
9751014
* Support for encodings other than UTF-8 / ASCII
976-
* API support for transactions, similar to [php](http://www.php.net/manual/en/mysqli.quickstart.transactions.php)

lib/Connection.js

+31
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ Connection.prototype.connect = function(cb) {
7373
};
7474

7575
Connection.prototype.changeUser = function(options, cb){
76+
cb = cb || function() {};
77+
7678
this._implyConnect();
7779

7880
if (typeof options === 'function') {
@@ -84,6 +86,8 @@ Connection.prototype.changeUser = function(options, cb){
8486
? Config.getCharsetNumber(options.charset)
8587
: this.config.charsetNumber;
8688

89+
var self = this;
90+
8791
return this._protocol.changeUser({
8892
user : options.user || this.config.user,
8993
password : options.password || this.config.password,
@@ -93,6 +97,33 @@ Connection.prototype.changeUser = function(options, cb){
9397
}, cb);
9498
};
9599

100+
Connection.prototype.beginTransaction = function(cb) {
101+
this._implyConnect();
102+
103+
var query = Connection.createQuery('START TRANSACTION', cb);
104+
query._connection = this;
105+
106+
return this._protocol._enqueue(query);
107+
};
108+
109+
Connection.prototype.commit = function(cb) {
110+
this._implyConnect();
111+
112+
var query = Connection.createQuery('COMMIT', cb);
113+
query._connection = this;
114+
115+
return this._protocol._enqueue(query);
116+
};
117+
118+
Connection.prototype.rollback = function(cb) {
119+
this._implyConnect();
120+
121+
var query = Connection.createQuery('ROLLBACK', cb);
122+
query._connection = this;
123+
124+
return this._protocol._enqueue(query);
125+
};
126+
96127
Connection.prototype.query = function(sql, values, cb) {
97128
this._implyConnect();
98129

test/integration/connection/test-transaction-commit.js

+24-28
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,32 @@ common.useTestDb(connection);
66

77
var table = 'transaction_test';
88
connection.query([
9-
'CREATE TEMPORARY TABLE `' + table + '` (',
10-
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
11-
'`title` varchar(255),',
12-
'PRIMARY KEY (`id`)',
13-
') ENGINE=InnoDB DEFAULT CHARSET=utf8'
14-
].join('\n'));
15-
16-
connection.query('START TRANSACTION');
17-
18-
var rowCount = 10;
19-
for (var i = 1; i <= rowCount; i++) {
9+
'CREATE TEMPORARY TABLE `' + table + '` (',
10+
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
11+
'`title` varchar(255),',
12+
'PRIMARY KEY (`id`)',
13+
') ENGINE=InnoDB DEFAULT CHARSET=utf8'
14+
].join('\n'));
15+
16+
connection.beginTransaction(function (err) {
17+
assert.ifError(err);
18+
2019
var row = {
21-
id: i,
22-
title: 'Row #' + i,
20+
id: 1,
21+
title: 'Test row'
2322
};
2423

25-
connection.query('INSERT INTO ' + table + ' SET ?', row);
26-
}
27-
28-
connection.query('COMMIT');
29-
30-
var rows = [];
31-
var query = connection.query('SELECT * FROM ' + table, function(err, _rows) {
32-
if (err) throw err;
33-
34-
rows = _rows;
35-
});
24+
connection.query('INSERT INTO ' + table + ' SET ?', row, function(err) {
25+
assert.ifError(err);
3626

37-
connection.end();
27+
connection.commit(function(err) {
28+
assert.ifError(err);
3829

39-
process.on('exit', function() {
40-
assert.equal(rows.length, rowCount);
41-
});
30+
connection.query('SELECT * FROM ' + table, function(err, rows) {
31+
assert.ifError(err);
32+
connection.end();
33+
assert.equal(rows.length, 1);
34+
});
35+
});
36+
});
37+
});

test/integration/connection/test-transaction-rollback.js

+24-28
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,32 @@ common.useTestDb(connection);
66

77
var table = 'transaction_test';
88
connection.query([
9-
'CREATE TEMPORARY TABLE `' + table + '` (',
10-
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
11-
'`title` varchar(255),',
12-
'PRIMARY KEY (`id`)',
13-
') ENGINE=InnoDB DEFAULT CHARSET=utf8'
14-
].join('\n'));
15-
16-
connection.query('START TRANSACTION');
17-
18-
var rowCount = 10;
19-
for (var i = 1; i <= rowCount; i++) {
9+
'CREATE TEMPORARY TABLE `' + table + '` (',
10+
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',
11+
'`title` varchar(255),',
12+
'PRIMARY KEY (`id`)',
13+
') ENGINE=InnoDB DEFAULT CHARSET=utf8'
14+
].join('\n'));
15+
16+
connection.beginTransaction(function (err) {
17+
assert.ifError(err);
18+
2019
var row = {
21-
id: i,
22-
title: 'Row #' + i,
20+
id: 1,
21+
title: 'Test row'
2322
};
2423

25-
connection.query('INSERT INTO ' + table + ' SET ?', row);
26-
}
27-
28-
connection.query('ROLLBACK');
29-
30-
var rows;
31-
var query = connection.query('SELECT * FROM ' + table, function(err, _rows) {
32-
if (err) throw err;
33-
34-
rows = _rows;
35-
});
24+
connection.query('INSERT INTO ' + table + ' SET ?', row, function(err) {
25+
assert.ifError(err);
3626

37-
connection.end();
27+
connection.rollback(function(err) {
28+
assert.ifError(err);
3829

39-
process.on('exit', function() {
40-
assert.equal(rows.length, 0);
41-
});
30+
connection.query('SELECT * FROM ' + table, function(err, rows) {
31+
assert.ifError(err);
32+
connection.end();
33+
assert.equal(rows.length, 0);
34+
});
35+
});
36+
});
37+
});

0 commit comments

Comments
 (0)