Socket
Socket
Sign inDemoInstall

mysql

Package Overview
Dependencies
1
Maintainers
4
Versions
65
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-alpha3 to 2.0.0-alpha4

lib/ConnectionConfig.js

19

Changes.md

@@ -7,2 +7,21 @@ # Changes

## v2.0.0-alpha4 (2012-10-03)
* Fix some OOB errors on resume()
* Fix quick pause() / resume() usage
* Properly parse host denied / similar errors
* Add Connection.ChangeUser functionality
* Make sure changeUser errors are fatal
* Enable formatting nested arrays for bulk inserts
* Add Connection.escape functionality
* Renamed 'close' to 'end' event
* Return parsed object instead of Buffer for GEOMETRY types
* Allow nestTables inline (using a string instead of a boolean)
* Check for ZEROFILL_FLAG and format number accordingly
* Add timezone support (default: local)
* Add custom typeCast functionality
* Export mysql column types
* Add connection flags functionality (#237)
* Exports drain event when queue finishes processing (#272, #271, #306)
## v2.0.0-alpha3 (2012-06-12)

@@ -9,0 +28,0 @@

9

index.js

@@ -1,5 +0,10 @@

var Connection = require('./lib/Connection');
var Connection = require('./lib/Connection');
var ConnectionConfig = require('./lib/ConnectionConfig');
var Types = require('./lib/protocol/constants/types');
exports.createConnection = function(config) {
return new Connection({config: config});
return new Connection({config: new ConnectionConfig(config)});
};
exports.escape = require('./lib/protocol/SqlString').escape;
exports.Types = Types;

@@ -1,7 +0,7 @@

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');

@@ -13,5 +13,6 @@ module.exports = Connection;

this.config = new Config(options.config);
this.config = options.config;
this._socket = options.socket;
this._timezone = options.config.timezone;
this._protocol = new Protocol({config: this.config});

@@ -25,7 +26,5 @@ this._connectCalled = false;

if (!this._socket) {
this._socket = (this.config.socketPath)
? Net.createConnection(this.config.socketPath)
: Net.createConnection(this.config.port, this.config.host);
}
this._socket = (this.config.socketPath)
? Net.createConnection(this.config.socketPath)
: Net.createConnection(this.config.port, this.config.host);

@@ -37,3 +36,4 @@ this._socket.pipe(this._protocol);

this._protocol.on('unhandledError', this._handleProtocolError.bind(this));
this._protocol.on('close', this._handleProtocolClose.bind(this));
this._protocol.on('drain', this._handleProtocolDrain.bind(this));
this._protocol.on('end', this._handleProtocolEnd.bind(this));
}

@@ -44,2 +44,23 @@

Connection.prototype.changeUser = function(options, cb){
this._implyConnect();
if (typeof options === 'function') {
cb = options;
options = {};
}
var charsetNumber = (options.charset)
? Config.getCharsetNumber(options.charset)
: this.config.charsetNumber;
return this._protocol.changeUser({
user : options.user || this.config.user,
password : options.password || this.config.password,
database : options.database || this.config.database,
charsetNumber : charsetNumber,
currentConfig : this.config
}, cb);
};
Connection.prototype.query = function(sql, values, cb) {

@@ -69,2 +90,3 @@ this._implyConnect();

options.sql = this.format(options.sql, values || []);
options.timeZone = this._timezone;

@@ -100,7 +122,7 @@ if (!('typeCast' in options)) {

Connection.prototype.escape = function(value) {
return SqlString.escape(value);
return SqlString.escape(value, true, this._timezone);
};
Connection.prototype.format = function(sql, values) {
return SqlString.format(sql, values);
return SqlString.format(sql, values, this._timezone);
};

@@ -116,6 +138,10 @@

Connection.prototype._handleProtocolClose = function(err) {
this.emit('close', err);
Connection.prototype._handleProtocolDrain = function(err) {
this.emit('drain', err);
};
Connection.prototype._handleProtocolEnd = function(err) {
this.emit('end', err);
};
Connection.prototype._implyConnect = function() {

@@ -122,0 +148,0 @@ if (!this._connectCalled) {

@@ -13,7 +13,12 @@ module.exports = ErrorPacket;

ErrorPacket.prototype.parse = function(parser) {
this.fieldCount = parser.parseUnsignedNumber(1);
this.errno = parser.parseUnsignedNumber(2);
this.sqlStateMarker = parser.parseString(1);
this.sqlState = parser.parseString(5);
this.message = parser.parsePacketTerminatedString();
this.fieldCount = parser.parseUnsignedNumber(1);
this.errno = parser.parseUnsignedNumber(2);
// sqlStateMarker ('#' = 0x23) indicates error packet format
if (parser.peak() === 0x23) {
this.sqlStateMarker = parser.parseString(1);
this.sqlState = parser.parseString(5);
}
this.message = parser.parsePacketTerminatedString();
};

@@ -24,5 +29,9 @@

writer.writeUnsignedNumber(2, this.errno);
writer.writeString(this.sqlStateMarker || '#');
writer.writeString(this.sqlState || '12345');
if (this.sqlStateMarker) {
writer.writeString(this.sqlStateMarker);
writer.writeString(this.sqlState);
}
writer.writeString(this.message);
};

@@ -19,2 +19,3 @@ module.exports = FieldPacket;

this.default = options.default;
this.zeroFill = options.zeroFill;
}

@@ -37,2 +38,5 @@

// parsed flags
this.zeroFill = (this.flags & 0x0040 ? true : false);
if (parser.reachedPacketEnd()) {

@@ -39,0 +43,0 @@ return;

@@ -45,5 +45,10 @@ module.exports = HandshakeInitializationPacket;

// 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);
}
};

@@ -50,0 +55,0 @@

@@ -18,2 +18,9 @@ module.exports = OkPacket;

this.message = parser.parsePacketTerminatedString();
this.changedRows = 0;
var m = this.message.match(/\schanged:\s*(\d+)/i);
if (m !== null) {
this.changedRows = parseInt(m[1], 10);
}
};

@@ -20,0 +27,0 @@

@@ -8,11 +8,24 @@ var Types = require('../constants/types');

RowDataPacket.prototype.parse = function(parser, fieldPackets, typeCast, nestTables) {
RowDataPacket.prototype.parse = function(parser, fieldPackets, typeCast, nestTables, timeZone) {
var self = this;
for (var i = 0; i < fieldPackets.length; i++) {
var fieldPacket = fieldPackets[i];
var value;
var value = (typeCast)
? this._typeCast(fieldPacket, parser)
: parser.parseLengthCodedString();
if (typeof typeCast == "function") {
value = typeCast(fieldPacket, parser, timeZone, function () {
return self._typeCast(fieldPacket, parser, timeZone);
});
} else {
value = (typeCast)
? this._typeCast(fieldPacket, parser, timeZone)
: ( (fieldPacket.charsetNr === Charsets.BINARY)
? parser.parseLengthCodedBuffer()
: parser.parseLengthCodedString() );
}
if (nestTables) {
if (typeof nestTables == "string" && nestTables.length) {
this[fieldPacket.table + nestTables + fieldPacket.name] = value;
} else if (nestTables) {
this[fieldPacket.table] = this[fieldPacket.table] || {};

@@ -26,3 +39,3 @@ this[fieldPacket.table][fieldPacket.name] = value;

RowDataPacket.prototype._typeCast = function(field, parser) {
RowDataPacket.prototype._typeCast = function(field, parser, timeZone) {
switch (field.type) {

@@ -34,5 +47,17 @@ case Types.TIMESTAMP:

var dateString = parser.parseLengthCodedString();
return (dateString === null)
? dateString
: new Date(dateString);
if (dateString === null) {
return null;
}
// Otherwise JS will assume the string to be in GMT rather than local
// time which is not what we want here. We always try to treat date
// objects and strings as if they were in local time.
if (field.type === Types.DATE) {
dateString += ' 00:00:00';
} else if (timeZone != 'local') {
// no timezone for date columns, there's no time.. so there's no time..zone
dateString += timeZone;
}
return new Date(dateString);
case Types.TINY:

@@ -46,3 +71,3 @@ case Types.SHORT:

var numberString = parser.parseLengthCodedString();
return (numberString === null)
return (numberString === null || (field.zeroFill && numberString[0] == "0"))
? numberString

@@ -61,2 +86,4 @@ : Number(numberString);

: parser.parseLengthCodedString();
case Types.GEOMETRY:
return parser.parseGeometryValue();
default:

@@ -63,0 +90,0 @@ return parser.parseLengthCodedString();

@@ -9,3 +9,3 @@ var IEEE_754_BINARY_64_PRECISION = Math.pow(2, 53);

this._buffer = null;
this._buffer = new Buffer(0);
this._longPacketBuffers = [];

@@ -15,3 +15,3 @@ this._offset = 0;

this._packetHeader = null;
this._packetParser = options.packetParser || function() {};
this._onPacket = options.onPacket || function() {};
this._nextPacketNumber = 0;

@@ -51,10 +51,25 @@ this._encoding = 'utf-8';

this._longPacketBuffers.push(this._buffer.slice(this._offset, this._packetEnd));
} else {
this._combineLongPacketBuffers();
this._packetParser(this._packetHeader);
this._advanceToNextPacket();
continue;
}
this._offset = this._packetEnd;
this._packetHeader = null;
this._packetEnd = null;
this._combineLongPacketBuffers();
// Try...finally to ensure exception safety. Unfortunately this is costing
// us up to ~10% performance in some benchmarks.
var hadException = true;
try {
this._onPacket(this._packetHeader);
hadException = false;
} finally {
this._advanceToNextPacket();
// If we had an exception, the parser while loop will be broken out
// of after the finally block. So we need to make sure to re-enter it
// to continue parsing any bytes that may already have been received.
if (hadException) {
process.nextTick(this.write.bind(this));
}
}
}

@@ -64,8 +79,8 @@ };

Parser.prototype.append = function(newBuffer) {
var oldBuffer = this._buffer;
if (!oldBuffer) {
this._buffer = newBuffer;
// If resume() is called, we don't pass a buffer to write()
if (!newBuffer) {
return;
}
var oldBuffer = this._buffer;
var bytesRemaining = this._bytesRemaining();

@@ -91,4 +106,6 @@ var newLength = bytesRemaining + newBuffer.length;

this._paused = false;
// A little hacky, but does the trick of resuming the parser
this.write(new Buffer(0));
// nextTick() to avoid entering write() multiple times within the same stack
// which would cause problems as write manipulates the state of the object.
process.nextTick(this.write.bind(this));
};

@@ -226,2 +243,59 @@

Parser.prototype.parseGeometryValue = function() {
var buffer = this.parseLengthCodedBuffer();
var offset = 4;
if (buffer === null) {
return null;
}
function parseGeometry() {
var result = null;
var byteOrder = buffer.readUInt8(offset); offset += 1;
var wkbType = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
switch(wkbType) {
case 1: // WKBPoint
var x = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
var y = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
result = {x: x, y: y};
break;
case 2: // WKBLineString
var numPoints = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
result = [];
for(var i=numPoints;i>0;i--) {
var x = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
var y = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
result.push({x: x, y: y});
}
break;
case 3: // WKBPolygon
var numRings = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
result = [];
for(var i=numRings;i>0;i--) {
var numPoints = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
var line = [];
for(var j=numPoints;j>0;j--) {
var x = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
var y = byteOrder? buffer.readDoubleLE(offset) : buffer.readDoubleBE(offset); offset += 8;
line.push({x: x, y: y});
}
result.push(line);
}
break;
case 4: // WKBMultiPoint
case 5: // WKBMultiLineString
case 6: // WKBMultiPolygon
case 7: // WKBGeometryCollection
var num = byteOrder? buffer.readUInt32LE(offset) : buffer.readUInt32BE(offset); offset += 4;
var result = [];
for(var i=num;i>0;i--) {
result.push(parseGeometry());
}
break;
}
return result;
}
return parseGeometry();
}
Parser.prototype.reachedPacketEnd = function() {

@@ -292,1 +366,7 @@ return this._offset === this._packetEnd;

};
Parser.prototype._advanceToNextPacket = function() {
this._offset = this._packetEnd;
this._packetHeader = null;
this._packetEnd = null;
};

@@ -19,24 +19,16 @@ var Parser = require('./Parser');

this._parser = new Parser({packetParser: this._parsePacket.bind(this)});
this._config = options.config || {};
this._callback = null;
this._fatalError = null;
this._quitSequence = null;
this._handshakeSequence = null;
this._destroyed = false;
this._queue = [];
this._parser = new Parser({onPacket: this._parsePacket.bind(this)});
this._config = options.config || {};
this._callback = null;
this._fatalError = null;
this._quitSequence = null;
this._handshakeSequence = null;
this._destroyed = false;
this._queue = [];
this._handshakeInitializationPacket = null;
}
Protocol.prototype.write = function(buffer) {
try {
this._parser.write(buffer);
return true;
} catch (err) {
err.code = err.code || 'PROTOCOL_PARSER_EXCEPTION';
err.fatal = true;
this._delegateError(err);
}
return false;
this._parser.write(buffer);
return true;
};

@@ -52,2 +44,6 @@

Protocol.prototype.changeUser = function(options, cb) {
return this._enqueue(new Sequences.ChangeUser(options, cb));
};
Protocol.prototype.quit = function(cb) {

@@ -61,3 +57,3 @@ return this._quitSequence = this._enqueue(new Sequences.Quit(cb));

this._quitSequence.end();
this.emit('close');
this.emit('end');
return;

@@ -159,4 +155,7 @@ }

if (Packet === Packets.HandshakeInitializationPacket) {
this._handshakeInitializationPacket = packet;
}
sequence[Packet.name](packet);
};

@@ -202,6 +201,15 @@

var sequence = this._queue[0];
if (sequence) {
this._parser.resetPacketNumber();
sequence.start();
if (!sequence) {
this.emit('drain');
return;
}
this._parser.resetPacketNumber();
if (sequence.constructor == Sequences.ChangeUser) {
sequence.start(this._handshakeInitializationPacket);
return;
}
sequence.start();
};

@@ -243,3 +251,3 @@

if (err.fatal) {
this.emit('close', err);
this.emit('end', err);
}

@@ -246,0 +254,0 @@ };

@@ -18,2 +18,3 @@ var Sequence = require('./Sequence');

this.nestTables = options.nestTables || false;
this.timeZone = options.timeZone || "Z";

@@ -63,11 +64,14 @@ this._resultSet = null;

Query.prototype['OkPacket'] = function(packet) {
if (!this._callback) {
this.emit('result', packet, this._index);
} else {
this._results.push(packet);
this._fields.push(undefined);
// try...finally for exception safety
try {
if (!this._callback) {
this.emit('result', packet, this._index);
} else {
this._results.push(packet);
this._fields.push(undefined);
}
} finally {
this._index++;
this._handleFinalResultPacket(packet);
}
this._index++;
this._handleFinalResultPacket(packet);
};

@@ -141,3 +145,3 @@

Query.prototype['RowDataPacket'] = function(packet, parser) {
packet.parse(parser, this._resultSet.fieldPackets, this.typeCast, this.nestTables);
packet.parse(parser, this._resultSet.fieldPackets, this.typeCast, this.nestTables, this.timeZone);

@@ -144,0 +148,0 @@ if (this._callback) {

@@ -53,4 +53,2 @@ var Util = require('util');

this._ended = true;
var self = this;
var args = arguments;

@@ -61,15 +59,16 @@ if (err) {

// Escape stack (so try..catch in Protocol#write does not interfer here)
process.nextTick(function() {
// try...finally for exception safety
try {
if (err) {
self.emit('error', err);
this.emit('error', err);
}
if (self._callback) {
self._callback.apply(self, args);
} finally {
try {
if (this._callback) {
this._callback.apply(this, arguments);
}
} finally {
this.emit('end');
}
self.emit('end');
});
}
};

@@ -82,4 +81,3 @@

Sequence.prototype['ErrorPacket'] = function(packet) {
var err = Sequence.packetToError(packet);
this.end(err);
this.end(this._packetToError(packet));
};

@@ -86,0 +84,0 @@

var SqlString = exports;
SqlString.escape = function(val, stringifyObjects) {
SqlString.escape = function(val, stringifyObjects, timeZone) {
if (val === undefined || val === null) {

@@ -14,3 +14,3 @@ return 'NULL';

if (val instanceof Date) {
val = SqlString.dateToString(val);
val = SqlString.dateToString(val, timeZone || "Z");
}

@@ -23,3 +23,3 @@

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

@@ -31,3 +31,3 @@

} else {
return SqlString.objectToValues(val);
return SqlString.objectToValues(val, timeZone);
}

@@ -50,9 +50,10 @@ }

function zeroPad(number) {
return (number < 10)
? '0' + number
: number;
}
SqlString.arrayToList = function(array, timeZone) {
return array.map(function(v) {
if (Array.isArray(v)) return '(' + SqlString.arrayToList(v) + ')';
return SqlString.escape(v, true, timeZone);
}).join(', ');
};
SqlString.format = function(sql, values) {
SqlString.format = function(sql, values, timeZone) {
values = [].concat(values);

@@ -65,14 +66,25 @@

return SqlString.escape(values.shift());
return SqlString.escape(values.shift(), false, timeZone);
});
};
SqlString.dateToString = function(date) {
var year = date.getFullYear();
var month = zeroPad(date.getMonth() + 1);
var day = zeroPad(date.getDate());
var hour = zeroPad(date.getHours());
var minute = zeroPad(date.getMinutes());
var second = zeroPad(date.getSeconds());
SqlString.dateToString = function(date, timeZone) {
var dt = new Date(date);
if (timeZone != 'local') {
tz = convertTimezone(timeZone);
dt.setTime(dt.getTime() + (dt.getTimezoneOffset() * 60000));
if (tz !== false) {
dt.setTime(dt.getTime() + (tz * 60000));
}
}
var year = dt.getFullYear();
var month = zeroPad(dt.getMonth() + 1);
var day = zeroPad(dt.getDate());
var hour = zeroPad(dt.getHours());
var minute = zeroPad(dt.getMinutes());
var second = zeroPad(dt.getSeconds());
return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;

@@ -96,3 +108,3 @@ };

SqlString.objectToValues = function(object) {
SqlString.objectToValues = function(object, timeZone) {
var values = [];

@@ -105,3 +117,3 @@ for (var key in object) {

values.push('`' + key + '` = ' + SqlString.escape(value, true));
values.push('`' + key + '` = ' + SqlString.escape(value, true, timeZone));
}

@@ -111,1 +123,15 @@

};
function zeroPad(number) {
return (number < 10) ? '0' + number : number;
}
function convertTimezone(tz) {
if (tz == "Z") return 0;
var m = tz.match(/([\+\-\s])(\d\d):?(\d\d)?/);
if (m) {
return (m[1] == '-' ? -1 : 1) * (parseInt(m[2], 10) + ((m[3] ? parseInt(m[3], 10) : 0) / 60)) * 60;
}
return false;
}

@@ -5,3 +5,3 @@ {

"description": "A node.js driver for mysql. It is written in JavaScript, does not require compiling, and is 100% MIT licensed.",
"version": "2.0.0-alpha3",
"version": "2.0.0-alpha4",
"repository": {

@@ -8,0 +8,0 @@ "url": ""

# 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)

@@ -8,3 +8,3 @@ ## Install

```bash
npm install mysql@2.0.0-alpha3
npm install mysql@2.0.0-alpha4
```

@@ -41,6 +41,6 @@

connection.query('SELECT 1', function(err, rows, fields) {
connection.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
if (err) throw err;
console.log('Query result: ', rows);
console.log('The solution is: ', rows[0].solution);
});

@@ -71,2 +71,3 @@

[Andrey Hristov]: http://andrey.hristov.com/
## Sponsors

@@ -91,8 +92,8 @@

So far all community activity has happened via the GitHub Issue system, however
additionally I have just started a mailing list and IRC channel where people
can ask questions and discuss things:
If you'd like to discuss this module, or ask questions about it, please use one
of the following:
* **Mailing list**: https://groups.google.com/forum/#!forum/node-mysql
* **IRC Channel**: #node-mysql (on freenode.net)
* **IRC Channel**: #node.js (on freenode.net, I pay attention to any message
including the term `mysql`)

@@ -142,5 +143,6 @@ ## Establishing connections

* `user`: The MySQL user to authenticate as.
* `password`: The passqword of that MySQL user.
* `password`: The password of that MySQL user.
* `database`: Name of the database to use for this connection (Optional).
* `charset`: The charset for the connection. (Default: `'UTF8_GENERAL_CI'`)
* `timezone`: The timezone used to store local dates. (Default: `'local'`)
* `insecureAuth`: Allow connecting to MySQL instances that ask for the old

@@ -153,2 +155,4 @@ (insecure) authentication method. (Default: `false`)

with this, it exposes you to SQL injection attacks. (Default: `false)
* `flags`: List of connection flags to use other than the default ones. It is
also possible to blacklist default ones. For more information, check [Connection Flags](#connection-flags).

@@ -159,3 +163,3 @@ In addition to passing these options as an object, you can also use a url

```js
var connection = mysql.createConnection('mysql://user:pass@host/db?debug=true&charset=BIG5_CHINESE_CI');
var connection = mysql.createConnection('mysql://user:pass@host/db?debug=true&charset=BIG5_CHINESE_CI&timezone=-0700');
```

@@ -183,3 +187,3 @@

An alternative way to end the connection is to call the `destroy()` method.
This will cause an immediate termination of the underlaying socket.
This will cause an immediate termination of the underlying socket.
Additionally `destroy()` guarantees that no more events or callbacks will be

@@ -194,5 +198,29 @@ triggered for the connection.

## Switching users / altering connection state
MySQL offers a changeUser command that allows you to alter the current user and
other aspects of the connection without shutting down the underlying socket:
```js
connection.changeUser({user : 'john'}, function(err) {
if (err) throw err;
});
```
The available options for this feature are:
* `user`: The name of the new user (defaults to the previous one).
* `password`: The password of the new user (defaults to the previous one).
* `charset`: The new charset (defaults to the previous one).
* `database`: The new database (defaults to the previous one).
A sometimes useful side effect of this functionality is that this function also
resets any connection state (variables, transactions, etc.).
Errors encountered during this operation are treated as fatal connection errors
by this module.
## Server disconnects
You may loose the connection to a MySQL server due to network problems, the
You may lose the connection to a MySQL server due to network problems, the
server timing you out, or the server crashing. All of these events are

@@ -203,14 +231,24 @@ considered fatal errors, and will have the `err.code =

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);
```

@@ -222,6 +260,4 @@

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.

@@ -261,3 +297,5 @@ ## Escaping query values

* Strings are safely escaped
* Arrays are turned into list, e.g. ['a', 'b'] turns into `'a', 'b'`
* Arrays are turned into list, e.g. `['a', 'b']` turns into `'a', 'b'`
* Nested arrays are turned into grouped lists (for bulk inserts), e.g. `[['a',
'b'], ['c', 'd']]` turns into `('a', 'b'), ('c', 'd')`
* Objects are turned into `key = 'val'` pairs. Nested objects are cast to

@@ -282,2 +320,11 @@ strings.

If you feel the need to escape queries by yourself, you can also use the escaping
function directly:
```js
var query = "SELECT * FROM posts WHERE title=" + mysql.escape("Hello MySQL");
console.log(query); // SELECT * FROM posts WHERE title='Hello MySQL'
```
## Getting the id of an inserted row

@@ -338,3 +385,3 @@

amount and size of your rows.
* `pause()` / `resume()` operate on the underlaying socket and parser. You are
* `pause()` / `resume()` operate on the underlying socket and parser. You are
guaranteed that no more `'result'` events will fire after calling `pause()`.

@@ -348,3 +395,3 @@ * You MUST NOT provide a callback to the `query()` method when streaming rows.

have a good use case for streaming large fields to and from MySQL, I'd love to
get your thoughts and conributions on this.
get your thoughts and contributions on this.

@@ -431,2 +478,18 @@ ## Multiple statement queries

Or use a string separator to have your results merged.
```js
var options = {sql: '...', nestTables: '_'};
connection.query(options, function(err, results) {
/* results will be an array like this now:
[{
table1_fieldA: '...',
table1_fieldB: '...',
table2_fieldA: '...',
table2_fieldB: '...'
}, ...]
*/
});
```
## Error handling

@@ -442,3 +505,3 @@

`'ER_ACCESS_DENIED_ERROR'`), a node.js error (e.g. `'ECONNREFUSED'`) or an
internal error (e.g. `'PROTOCOL_PARSER_EXCEPTION'`).
internal error (e.g. `'PROTOCOL_CONNECTION_LOST'`).
* `err.fatal`: Boolean, indicating if this error is terminal to the connection

@@ -501,3 +564,3 @@ object.

**tl;dr:** This module does not want you to to deal with silent failures. You
**tl;dr:** This module does not want you to deal with silent failures. You
should always provide callbacks to your method calls. If you want to ignore

@@ -507,6 +570,12 @@ 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 callback functions throws an error which you're catching using
'uncaughtException' or a domain.
## Type casting

@@ -541,3 +610,3 @@

* VARBINARY
* BIT (last byte will be filled with 0 bits as neccessary)
* BIT (last byte will be filled with 0 bits as necessary)

@@ -575,2 +644,48 @@ ### String

## Connection Flags
If, for any reason, you would like to change the default connection flags, you
can use the connection option `flags`. Pass a string with a comma separated list
of items to add to the default flags. If you don't want a default flag to be used
prepend the flag with a minus sign. To add a flag that is not in the default list, don't prepend it with a plus sign, just write the flag name (case insensitive).
**Please note that some available flags that are not default are still not supported
(e.g.: SSL, Compression). Use at your own risk.**
### Example
The next example blacklists FOUND_ROWS flag from default connection flags.
```js
var connection = mysql.createConnection("mysql://localhost/test?flags=-FOUND_ROWS")
```
### Default Flags
- LONG_PASSWORD
- FOUND_ROWS
- LONG_FLAG
- CONNECT_WITH_DB
- ODBC
- LOCAL_FILES
- IGNORE_SPACE
- PROTOCOL_41
- IGNORE_SIGPIPE
- TRANSACTIONS
- RESERVED
- SECURE_CONNECTION
- MULTI_RESULTS
- MULTI_STATEMENTS (used if `multipleStatements` option is activated)
### Other Available Flags
- NO_SCHEMA
- COMPRESS
- INTERACTIVE
- SSL
- PS_MULTI_RESULTS
- PLUGIN_AUTH
- SSL_VERIFY_SERVER_CERT
- REMEMBER_OPTIONS
## Debugging and reporting problems

@@ -577,0 +692,0 @@

@@ -23,8 +23,11 @@ var common = exports;

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',
user: 'root'
}, config);

@@ -36,4 +39,4 @@ } else {

user : process.env.MYSQL_USER,
password : process.env.MYSQL_PASSWORD,
}, config)
password : process.env.MYSQL_PASSWORD
}, config);
}

@@ -40,0 +43,0 @@

@@ -44,3 +44,3 @@ // An experimental fake MySQL server for tricky integration tests. Expanded

this._socket = socket;
this._parser = new Parser({packetParser: this._parsePacket.bind(this)});
this._parser = new Parser({onPacket: this._parsePacket.bind(this)});

@@ -47,0 +47,0 @@ this._handshakeInitializationPacket = null;

@@ -1,1 +0,7 @@

require('urun')(__dirname)
var options = {};
if (process.env.FILTER) {
options.include = new RegExp(process.env.FILTER + '.*\\.js$');
}
require('urun')(__dirname, options);

@@ -40,2 +40,6 @@ var common = require('../../common');

'nested arrays are turned into grouped lists': function() {
assert.equal(SqlString.escape([[1,2,3], [4,5,6], ['a', 'b', {nested: true}]]), "(1, 2, 3), (4, 5, 6), ('a', 'b', '[object Object]')");
},
'nested objects inside arrays are cast to strings': function() {

@@ -73,3 +77,3 @@ assert.equal(SqlString.escape([1, {nested: true}, 2]), "1, '[object Object]', 2");

'\u001 (ascii 26) gets replaced with \\Z': function() {
'\u001a (ascii 26) gets replaced with \\Z': function() {
assert.equal(SqlString.escape('Sup\u001aer'), "'Sup\\Zer'");

@@ -88,3 +92,3 @@ },

var expected = '2012-05-07 11:42:03';
var date = new Date(expected);
var date = new Date(Date.UTC(2012, 4, 7, 11, 42, 3));
var string = SqlString.escape(date);

@@ -108,3 +112,3 @@

assert.equal(SqlString.escape(Infinity), 'Infinity');
},
}
});

@@ -111,0 +115,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc