Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ON DUPLICATE KEY UPDATE produces wrong affectedRows #237

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# node-mysql

[![Build Status](https://secure.travis-ci.org/felixge/node-mysql.png?branch=v2.0)](http://travis-ci.org/felixge/node-mysql)
[![Build Status](https://secure.travis-ci.org/felixge/node-mysql.png)](http://travis-ci.org/felixge/node-mysql)

## Install

Expand Down Expand Up @@ -216,28 +216,36 @@ considered fatal errors, and will have the `err.code =
'PROTOCOL_CONNECTION_LOST'`. See the [Error Handling](#error-handling) section
for more information.

The best way to be notified about a connection termination is to listen for the
`'close'` event:
The best way to handle such unexpected disconnects is shown below:

```js
connection.on('close', function(err) {
if (err) {
// We did not expect this connection to terminate
function handleDisconnect(connection) {
connection.on('error', function(err) {
if (!err.fatal) {
return;
}

if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
throw err;
}

console.log('Re-connecting lost connection: ' + err.stack);

connection = mysql.createConnection(connection.config);
} else {
// We expected this to happen, end() was called.
}
});
handleDisconnect(connection);
connection.connect();
});
}

handleDisconnect(connection);
```

As you can see in the example above, re-connecting a connection is done by
establishing a new connection. Once terminated, an existing connection object
cannot be re-connected by design.

Please note that you will also receive a `'close'` event with an `err` argument
when a connection attempt fails because of bad credentials. If you find this
cumbersome to work with, please post to the node-mysql mailing list to discuss
improvements.
This logic will also be part of connection pool support once I add that to this
library.

## Escaping query values

Expand Down Expand Up @@ -511,14 +519,14 @@ should always provide callbacks to your method calls. If you want to ignore
this advice and suppress unhandled errors, you can do this:

```js
// I am Chuck Noris:
// I am Chuck Norris:
connection.on('error', function() {});
```

## Exception Safety

This module is exception safe. That means you can continue to use it, even if
one of your callbacks to it throws an error which you're catching using
one of your callback functions throws an error which you're catching using
'uncaughtException' or a domain.

## Type casting
Expand Down
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var Connection = require('./lib/Connection');
var Connection = require('./lib/Connection');
var ConnectionConfig = require('./lib/ConnectionConfig');

exports.createConnection = function(config) {
return new Connection({config: config});
return new Connection({config: new ConnectionConfig(config)});
};
14 changes: 7 additions & 7 deletions lib/Connection.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
var Net = require('net');
var Config = require('./Config');
var Protocol = require('./protocol/Protocol');
var SqlString = require('./protocol/SqlString');
var EventEmitter = require('events').EventEmitter;
var Util = require('util');
var Net = require('net');
var ConnectionConfig = require('./ConnectionConfig');
var Protocol = require('./protocol/Protocol');
var SqlString = require('./protocol/SqlString');
var EventEmitter = require('events').EventEmitter;
var Util = require('util');

module.exports = Connection;
Util.inherits(Connection, EventEmitter);
function Connection(options) {
EventEmitter.call(this);

this.config = new Config(options.config);
this.config = options.config;

this._socket = options.socket;
this._protocol = new Protocol({config: this.config});
Expand Down
12 changes: 6 additions & 6 deletions lib/Config.js → lib/ConnectionConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ var urlParse = require('url').parse;
var ClientConstants = require('./protocol/constants/client');
var Charsets = require('./protocol/constants/charsets');

module.exports = Config;
function Config(options) {
module.exports = ConnectionConfig;
function ConnectionConfig(options) {
if (typeof options === 'string') {
options = Config.parseUrl(options);
options = ConnectionConfig.parseUrl(options);
}

this.host = options.host || 'localhost';
Expand All @@ -22,7 +22,7 @@ function Config(options) {

this.maxPacketSize = 0;
this.charsetNumber = (options.charset)
? Config.getCharsetNumber(options.charset)
? ConnectionConfig.getCharsetNumber(options.charset)
: Charsets.UTF8_GENERAL_CI;

this.clientFlags =
Expand All @@ -45,11 +45,11 @@ function Config(options) {
}
}

Config.getCharsetNumber = function(charset) {
ConnectionConfig.getCharsetNumber = function(charset) {
return Charsets[charset];
};

Config.parseUrl = function(url) {
ConnectionConfig.parseUrl = function(url) {
url = urlParse(url, true);

var options = {
Expand Down
7 changes: 1 addition & 6 deletions lib/protocol/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = Parser;
function Parser(options) {
options = options || {};

this._buffer = null;
this._buffer = new Buffer(0);
this._longPacketBuffers = [];
this._offset = 0;
this._packetEnd = null;
Expand Down Expand Up @@ -79,11 +79,6 @@ Parser.prototype.append = function(newBuffer) {
}

var oldBuffer = this._buffer;
if (!oldBuffer) {
this._buffer = newBuffer;
return;
}

var bytesRemaining = this._bytesRemaining();
var newLength = bytesRemaining + newBuffer.length;

Expand Down
9 changes: 8 additions & 1 deletion lib/protocol/SqlString.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ SqlString.escape = function(val, stringifyObjects) {
}

if (Array.isArray(val)) {
return val.map(SqlString.escape).join(', ');
return SqlString.arrayToList(val);
}

if (typeof val === 'object') {
Expand All @@ -44,6 +44,13 @@ SqlString.escape = function(val, stringifyObjects) {
return "'"+val+"'";
};

SqlString.arrayToList = function(array) {
return array.map(function(v) {
if (Array.isArray(v)) return '(' + SqlString.arrayToList(v) + ')';
return SqlString.escape(v, true);
}).join(', ');
};

function zeroPad(number) {
return (number < 10)
? '0' + number
Expand Down
9 changes: 7 additions & 2 deletions lib/protocol/packets/HandshakeInitializationPacket.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,14 @@ HandshakeInitializationPacket.prototype.parse = function(parser) {
}

// According to the docs this should be 0x00 terminated, but MariaDB does
// not do this, so we assume this string to be packet terminated. Any trailing
// 0x00 byte will be automatically ignored.
// not do this, so we assume this string to be packet terminated.
this.pluginData = parser.parsePacketTerminatedString();

// However, if there is a trailing '\0', strip it
var lastChar = this.pluginData.length - 1;
if (this.pluginData[lastChar] === '\0') {
this.pluginData = this.pluginData.substr(0, lastChar);
}
};

HandshakeInitializationPacket.prototype.write = function(writer) {
Expand Down
7 changes: 5 additions & 2 deletions test/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ common.testDatabase = process.env.MYSQL_DATABASE;

var Mysql = require('../');

common.isTravis = function() {
return Boolean(process.env.CI);
};

common.createConnection = function(config) {
var isTravis = Boolean(process.env.CI);
if (isTravis) {
if (common.isTravis()) {
// see: http://about.travis-ci.org/docs/user/database-setup/
config = _.extend({
user: 'root',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({password: 'INVALID PASSWORD'});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
// cause unexpected behavior for queries that were enqueued under the
// assumption of changeUser to succeed.

var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

if (common.isTravis()) {
return console.log('skipping - travis mysql does not support this test');
}

var err;
connection.changeUser({user: 'does-not-exist'}, function(_err) {
err = _err;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

if (common.isTravis()) {
return console.log('skipping - travis mysql does not support this test');
}

connection.query('CREATE DATABASE ' + common.testDatabase, function(err) {
if (err && err.code !== 'ER_DB_CREATE_EXISTS') throw err;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// the connection instance ending up in a bad state where it doesn't work
// properly or doesn't execute the next sequence anymore.

var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({password: common.bogusPassword});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({password: common.bogusPassword});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({port: common.bogusPort});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({port: common.bogusPort});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({port: common.bogusPort});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({port: common.fakeServerPort});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({port: common.bogusPort});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Experimental: https://github.com/felixge/node-mysql/issues/198

var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({multipleStatements: true});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({multipleStatements: true});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection({multipleStatements: true});
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var common = require('../common');
var common = require('../../common');
var connection = common.createConnection();
var assert = require('assert');

Expand Down
Loading