Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mysql

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mysql - npm Package Compare versions

Comparing version 2.0.0-alpha2 to 2.0.0-alpha3

lib/protocol/packets/EmptyPacket.js

29

benchmark/parse-100k-blog-rows.js

@@ -5,2 +5,3 @@ var lib = __dirname + '/../lib';

var PacketWriter = require(lib + '/protocol/PacketWriter');
var Parser = require(lib + '/protocol/Parser');

@@ -15,2 +16,4 @@ var options = {

function createBuffers() {
var parser = new Parser();
process.stderr.write('Creating row buffers ... ');

@@ -23,13 +26,13 @@

var buffers = [
createPacketBuffer(number++, new Packets.ResultSetHeaderPacket({fieldCount: 2})),
createPacketBuffer(number++, new Packets.FieldPacket({catalog: 'foo', name: 'id'})),
createPacketBuffer(number++, new Packets.FieldPacket({catalog: 'foo', name: 'text'})),
createPacketBuffer(number++, new Packets.EofPacket()),
createPacketBuffer(parser, new Packets.ResultSetHeaderPacket({fieldCount: 2})),
createPacketBuffer(parser, new Packets.FieldPacket({catalog: 'foo', name: 'id'})),
createPacketBuffer(parser, new Packets.FieldPacket({catalog: 'foo', name: 'text'})),
createPacketBuffer(parser, new Packets.EofPacket()),
];
for (var i = 0; i < options.rows; i++) {
buffers.push(createRowDataPacketBuffer(id++, number++));
buffers.push(createRowDataPacketBuffer(parser, number++));
}
buffers.push(createPacketBuffer(number++, new Packets.EofPacket));
buffers.push(createPacketBuffer(parser, new Packets.EofPacket));

@@ -49,15 +52,15 @@ buffers = mergeBuffers(buffers);

function createPacketBuffer(number, packet) {
var writer = new PacketWriter(number % 256);
function createPacketBuffer(parser, packet) {
var writer = new PacketWriter();
packet.write(writer);
return writer.toBuffer();
return writer.toBuffer(parser);
}
function createRowDataPacketBuffer(id, number) {
var writer = new PacketWriter(number++ % 256);
function createRowDataPacketBuffer(parser, number) {
var writer = new PacketWriter();
writer.writeLengthCodedString(id);
writer.writeLengthCodedString(parser._nextPacketNumber);
writer.writeLengthCodedString('Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has sur');
return writer.toBuffer();
return writer.toBuffer(parser);
}

@@ -64,0 +67,0 @@

@@ -7,6 +7,22 @@ # Changes

## v2.0.0-alpha2 (unreleased)
## v2.0.0-alpha3 (2012-06-12)
* Implement support for `LOAD DATA LOCAL INFILE` queries (#182).
* Support OLD\_PASSWORD() accounts like 0.9.x did. You should still upgrade any
user accounts in your your MySQL user table that has short (16 byte) Password
values. Connecting to those accounts is not secure. (#204)
* Ignore function values when escaping objects, allows to use RowDataPacket
objects as query arguments. (Alex Gorbatchev, #213)
* Handle initial error packets from server such as `ER_HOST_NOT_PRIVILEGED`.
* Treat `utf8\_bin` as a String, not Buffer. (#214)
* Handle empty strings in first row column value. (#222)
* Honor Connection#nestTables setting for queries. (#221)
* Remove `CLIENT_INTERACTIVE` flag from config. Improves #225.
* Improve docs for connections settings.
* Implement url string support for Connection configs.
## v2.0.0-alpha2 (2012-05-31)
* Specify escaping before for NaN / Infinity (they are as unquoted constants).
* Support for unix domain socket connections (use: {socketPath: '...'})
* Support for unix domain socket connections (use: {socketPath: '...'}).
* Fix type casting for NULL values for Date/Number fields

@@ -20,3 +36,3 @@ * Add `fields` argument to `query()` as well as `'fields'` event. This is

with overlapping column names.
* Fix ? placeholder mechanism for values containing '?' characters(#205)
* Fix ? placeholder mechanism for values containing '?' characters (#205).
* Detect when `connect()` is called more than once on a connection and provide

@@ -27,3 +43,3 @@ the user with a good error message for it (#204).

and also make the charset user configurable.
* Fix BLOB type casting for `TINY_BLOG`, `MEDIUM_BLOB` and `LONG_BLOB`
* Fix BLOB type casting for `TINY_BLOG`, `MEDIUM_BLOB` and `LONG_BLOB`.
* Add support for sending and receiving large (> 16 MB) packets.

@@ -30,0 +46,0 @@

@@ -0,1 +1,2 @@

var urlParse = require('url').parse;
var ClientConstants = require('./protocol/constants/client');

@@ -6,10 +7,15 @@ var Charsets = require('./protocol/constants/charsets');

function Config(options) {
this.host = options.host || 'localhost';
this.port = options.port || 3306;
this.socketPath = options.socketPath;
this.user = options.user || undefined;
this.password = options.password || undefined;
this.database = options.database;
this.debug = options.debug;
this.typeCast = (options.typeCast === undefined)
if (typeof options === 'string') {
options = Config.parseUrl(options);
}
this.host = options.host || 'localhost';
this.port = options.port || 3306;
this.socketPath = options.socketPath;
this.user = options.user || undefined;
this.password = options.password || undefined;
this.database = options.database;
this.insecureAuth = options.insecureAuth || false;
this.debug = options.debug;
this.typeCast = (options.typeCast === undefined)
? true

@@ -32,3 +38,2 @@ : options.typeCast;

ClientConstants.CLIENT_PROTOCOL_41 |
ClientConstants.CLIENT_INTERACTIVE |
ClientConstants.CLIENT_IGNORE_SIGPIPE |

@@ -44,1 +49,33 @@ ClientConstants.CLIENT_TRANSACTIONS |

}
Config.parseUrl = function(url) {
url = urlParse(url, true);
var options = {
host : url.hostname,
port : url.port,
database : url.pathname.substr(1),
};
if (url.auth) {
var auth = url.auth.split(':');
options.user = auth[0];
options.password = auth[1];
}
if (url.query) {
for (var key in url.query) {
var value = url.query[key];
try {
// Try to parse this as a JSON expression first
options[key] = JSON.parse(value);
} catch (err) {
// Otherwise assume it is a plain string
options[key] = value;
}
}
}
return options;
};
module.exports = ErrorPacket;
function ErrorPacket() {
this.fieldCount = undefined;
this.errno = undefined;
this.sqlStateMarker = undefined;
this.sqlState = undefined;
this.message = undefined;
function ErrorPacket(options) {
options = options || {};
this.fieldCount = options.fieldCount;
this.errno = options.errno;
this.sqlStateMarker = options.sqlStateMarker;
this.sqlState = options.sqlState;
this.message = options.message;
}

@@ -17,1 +19,9 @@

};
ErrorPacket.prototype.write = function(writer) {
writer.writeUnsignedNumber(1, 0xff);
writer.writeUnsignedNumber(2, this.errno);
writer.writeString(this.sqlStateMarker || '#');
writer.writeString(this.sqlState || '12345');
writer.writeString(this.message);
};

@@ -12,7 +12,7 @@ module.exports = ResultSetHeaderPacket;

if (parser.reachedPacketEnd()) {
return;
}
if (parser.reachedPacketEnd()) return;
this.extra = parser.parseLengthCodedNumber();
this.extra = (this.fieldCount === null)
? parser.parsePacketTerminatedString()
: parser.parseLengthCodedNumber();
};

@@ -19,0 +19,0 @@

@@ -1,3 +0,3 @@

var Types = require('../constants/types');
var FieldFlags = require('../constants/field_flags');
var Types = require('../constants/types');
var Charsets = require('../constants/charsets');

@@ -54,3 +54,3 @@ module.exports = RowDataPacket;

case Types.BLOB:
return (field.flags & FieldFlags.BINARY_FLAG)
return (field.charsetNr === Charsets.BINARY)
? parser.parseLengthCodedBuffer()

@@ -57,0 +57,0 @@ : parser.parseLengthCodedString();

@@ -10,3 +10,3 @@ var BIT_16 = Math.pow(2, 16);

function PacketWriter() {
this._buffer = null;
this._buffer = new Buffer(0);
this._offset = 0;

@@ -13,0 +13,0 @@ }

@@ -15,6 +15,14 @@ var Sequence = require('./Sequence');

Handshake.prototype.determinePacket = function() {
Handshake.prototype.determinePacket = function(firstByte) {
if (firstByte === 0xff) {
return Packets.ErrorPacket;
}
if (!this._handshakeInitializationPacket) {
return Packets.HandshakeInitializationPacket;
}
if (firstByte === 0xfe) {
return Packets.UseOldPasswordPacket;
}
};

@@ -35,2 +43,21 @@

Handshake.prototype['UseOldPasswordPacket'] = function(packet) {
if (!this._config.insecureAuth) {
var err = new Error(
'MySQL server is requesting the old and insecure pre-4.1 auth mechanism.' +
'Upgrade the user password or use the {insecureAuth: true} option.'
);
err.code = 'HANDSHAKE_INSECURE_AUTH';
err.fatal = true;
this.end(err);
return;
}
this.emit('packet', new Packets.OldPasswordPacket({
scrambleBuff : Auth.scramble323(this._handshakeInitializationPacket.scrambleBuff(), this._config.password),
}));
};
Handshake.prototype['ErrorPacket'] = function(packet) {

@@ -37,0 +64,0 @@ var err = this._packetToError(packet, true);

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

var ServerStatus = require('../constants/server_status');
var fs = require('fs');

@@ -17,3 +18,3 @@ module.exports = Query;

: options.typeCast;
this.nestTables = false;
this.nestTables = options.nestTables || false;

@@ -24,2 +25,3 @@ this._resultSet = null;

this._index = 0;
this._loadError = null;
}

@@ -32,3 +34,13 @@

Query.prototype.determinePacket = function(firstByte, parser) {
if (firstByte === 0 || firstByte === 255) {
if (firstByte === 0) {
// If we have a resultSet and got one eofPacket
if (this._resultSet && this._resultSet.eofPackets.length === 1) {
// Then this is a RowDataPacket with an empty string in the first column.
// See: https://github.com/felixge/node-mysql/issues/222
} else {
return;
}
}
if (firstByte === 255) {
return;

@@ -82,2 +94,7 @@ }

this._resultSet = new ResultSet(packet);
// used by LOAD DATA LOCAL INFILE queries
if (packet.fieldCount === null) {
this._sendLocalDataFile(packet.extra);
}
};

@@ -123,3 +140,3 @@

this.end(null, results, fields);
this.end(this._loadError, results, fields);
};

@@ -133,5 +150,17 @@

} else {
// @TODO Multiple results
this.emit('result', packet, this._index);
}
};
Query.prototype._sendLocalDataFile = function(path) {
var self = this;
fs.readFile(path, 'utf-8', function(err, data) {
if (err) {
self._loadError = err;
} else {
self.emit('packet', new Packets.LocalDataFilePacket(data));
}
self.emit('packet', new Packets.EmptyPacket());
});
};

@@ -95,2 +95,6 @@ var SqlString = exports;

var value = object[key];
if(typeof value === 'function') {
continue;
}
values.push('`' + key + '` = ' + SqlString.escape(value, true));

@@ -97,0 +101,0 @@ }

@@ -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-alpha2",
"version": "2.0.0-alpha3",
"repository": {

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

@@ -5,2 +5,20 @@ # node-mysql

## Install
```bash
npm install mysql@2.0.0-alpha3
```
Despite the alpha tag, this is the recommended version for new applications.
For information about the previous 0.9.x releases, visit the [v0.9 branch][].
Sometimes I may also ask you to install the latest version from Github to check
if a bugfix is working. In this case, please do:
```
npm install git://github.com/felixge/node-mysql.git
```
[v0.9 branch]: https://github.com/felixge/node-mysql/tree/v0.9
## Introduction

@@ -57,2 +75,4 @@

* [Transloadit](http://transloadit.com) (my startup, we do file uploading &
video encoding as a service, check it out)
* [Joyent](http://www.joyent.com/)

@@ -84,11 +104,5 @@ * [pinkbike.com](http://pinkbike.com/)

var connection = mysql.createConnection({
host : String, // defaults to 'localhost'
port : Number, // defaults to 3306
socketPath : String, // defaults to undefined
user : String, // defaults to undefined
password : String, // defaults to undefined
database : String, // defaults to undefined
charset : String, // defaults to 'UTF8_GENERAL_CI'
typeCast : Boolean, // defaults to true
debug : Boolean, // defaults to false
host : 'example.org',
user : 'bob',
password : 'secret',
});

@@ -117,2 +131,33 @@

## Connection options
When establishing a connection, you can set the following options:
* `host`: The hostname of the database you are connecting to. (Default:
`localhost`)
* `port`: The port number to connect to. (Default: `3306`)
* `socketPath`: The path to a unix domain socket to connect to. When used `host`
and `port` are ignored.
* `user`: The MySQL user to authenticate as.
* `password`: The passqword 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'`)
* `insecureAuth`: Allow connecting to MySQL instances that ask for the old
(insecure) authentication method. (Default: `false`)
* `typeCast`: Determines if column values should be converted to native
JavaScript types. (Default: `true`)
* `debug`: Prints protocol details to stdout. (Default: `false`)
* `multipleStatements`: Allow multiple mysql statements per query. Be careful
with this, it exposes you to SQL injection attacks. (Default: `false)
In addition to passing these options as an object, you can also use a url
string. For example:
```js
var connection = mysql.createConnection('mysql://user:pass@host/db?debug=true&charset=BIG5_CHINESE_CI');
```
Note: The query values are first attempted to be parsed as JSON, and if that
fails assumed to be plaintext strings.
## Terminating connections

@@ -532,14 +577,2 @@

## FAQ
I have yet to write this, but it will include:
* What benefits does this driver have over compiled alternatives? (portability,
license, docs)
* How is the performance of this module compared to the alternatives? (great)
* Is there commercial support for this driver? (nodefirm?)
* What features are missing? (stored procedures, transactions, pause, etc.)
* How can I contribute? (explain)
* What are the goals of this project?
## Todo

@@ -546,0 +579,0 @@

@@ -6,3 +6,4 @@ var common = exports;

common.lib = path.join(__dirname, '../lib');
common.lib = path.join(__dirname, '../lib');
common.fixtures = path.join(__dirname, 'fixtures');

@@ -9,0 +10,0 @@ // Useful for triggering ECONNREFUSED errors on connect()

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

var Parser = require('../lib/protocol/Parser');
var Auth = require('../lib/protocol/Auth');
var EventEmitter = require('events').EventEmitter;

@@ -46,3 +47,6 @@ var Util = require('util');

this._clientAuthenticationPacket = false;
this._handshakeInitializationPacket = null;
this._clientAuthenticationPacket = null;
this._oldPasswordPacket = null;
this._handshakeOptions = {};

@@ -52,6 +56,17 @@ socket.on('data', this._handleData.bind(this));

FakeConnection.prototype.handshake = function() {
this._sendPacket(new Packets.HandshakeInitializationPacket({
FakeConnection.prototype.handshake = function(options) {
this._handshakeOptions = options || {};
this._handshakeInitializationPacket = new Packets.HandshakeInitializationPacket({
scrambleBuff1: new Buffer(8),
scrambleBuff2: new Buffer(12),
});
this._sendPacket(this._handshakeInitializationPacket);
};
FakeConnection.prototype.deny = function(message, errno) {
this._sendPacket(new Packets.ErrorPacket({
message: message,
errno: errno,
}));

@@ -79,3 +94,30 @@ };

this._clientAuthenticationPacket = packet;
this._sendPacket(new Packets.OkPacket());
if (this._handshakeOptions.oldPassword) {
this._sendPacket(new Packets.UseOldPasswordPacket());
} else {
if (this._handshakeOptions.user || this._handshakeOptions.password) {
throw new Error('not implemented');
}
this._sendPacket(new Packets.OkPacket());
this._parser.resetPacketNumber();
}
break;
case Packets.OldPasswordPacket:
this._oldPasswordPacket = packet;
var expected = Auth.scramble323(this._handshakeInitializationPacket.scrambleBuff(), this._handshakeOptions.password);
var got = packet.scrambleBuff;
var toString = function(buffer) {
return Array.prototype.slice.call(buffer).join(',');
};
if (toString(expected) === toString(got)) {
this._sendPacket(new Packets.OkPacket());
} else {
this._sendPacket(new Packets.ErrorPacket());
}
this._parser.resetPacketNumber();

@@ -94,2 +136,4 @@ break;

return Packets.ClientAuthenticationPacket;
} else if (this._handshakeOptions.oldPassword && !this._oldPasswordPacket) {
return Packets.OldPasswordPacket;
}

@@ -96,0 +140,0 @@

@@ -18,4 +18,9 @@ var common = require('../common');

var options = {
nestTables: true,
sql: 'SELECT * FROM ' + table,
};
var rows;
var query = connection.query('SELECT * FROM ' + table, function(err, _rows) {
var query = connection.query(options, function(err, _rows) {
if (err) throw err;

@@ -26,4 +31,2 @@

query.nestTables = true;
connection.end();

@@ -30,0 +33,0 @@

@@ -7,52 +7,50 @@ var common = require('../common');

var expected = {
'DECIMAL' : '0.330',
'TINYINT' : 1,
'SMALLINT' : 2,
'INT' : 3,
'FLOAT' : 4.5,
'DOUBLE' : 5.5,
'BIGINT' : '6',
'MEDIUMINT' : 7,
'YEAR' : 2012,
'TIMESTAMP' : new Date('2012-05-12 11:00:23'),
'DATETIME' : new Date('2012-05-12 11:02:32'),
'DATE' : new Date('2012-05-12'),
'TIME' : '13:13:23',
'BINARY' : new Buffer([0, 1, 254, 255]),
'VARBINARY' : new Buffer([0, 1, 254, 255]),
'TINYBLOB' : new Buffer([0, 1, 254, 255]),
'MEDIUMBLOB' : new Buffer([0, 1, 254, 255]),
'LONGBLOB' : new Buffer([0, 1, 254, 255]),
'BLOB' : new Buffer([0, 1, 254, 255]),
'BIT' : new Buffer([0, 1, 254, 255]),
'CHAR' : 'Hello',
'VARCHAR' : 'Hello',
'TINYTEXT' : 'Hello World',
'MEDIUMTEXT' : 'Hello World',
'LONGTEXT' : 'Hello World',
'TEXT' : 'Hello World',
};
var tests = [
{type: 'decimal(3,3)', insert: '0.330'},
{type: 'decimal(3,3)', insert: 0.33, expect: '0.330'},
{type: 'tinyint', insert: 1},
{type: 'smallint', insert: 2},
{type: 'int', insert: 3},
{type: 'float', insert: 4.5},
{type: 'double', insert: 5.5},
{type: 'bigint', insert: '6'},
{type: 'bigint', insert: 6, expect: '6'},
{type: 'mediumint', insert: 7},
{type: 'year', insert: 2012},
{type: 'timestamp', insert: new Date('2012-05-12 11:00:23')},
{type: 'datetime', insert: new Date('2012-05-12 12:00:23')},
{type: 'date', insert: new Date('2012-05-12')},
{type: 'time', insert: '13:13:23'},
{type: 'binary(4)', insert: new Buffer([0, 1, 254, 255])},
{type: 'varbinary(4)', insert: new Buffer([0, 1, 254, 255])},
{type: 'tinyblob', insert: new Buffer([0, 1, 254, 255])},
{type: 'mediumblob', insert: new Buffer([0, 1, 254, 255])},
{type: 'longblob', insert: new Buffer([0, 1, 254, 255])},
{type: 'blob', insert: new Buffer([0, 1, 254, 255])},
{type: 'bit(32)', insert: new Buffer([0, 1, 254, 255])},
{type: 'char(5)', insert: 'Hello'},
{type: 'varchar(5)', insert: 'Hello'},
{type: 'varchar(3) character set utf8 collate utf8_bin', insert: 'bin'},
{type: 'tinytext', insert: 'Hello World'},
{type: 'mediumtext', insert: 'Hello World'},
{type: 'longtext', insert: 'Hello World'},
{type: 'text', insert: 'Hello World'},
];
var table = 'type_casting';
var schema = [];
var inserts = [];
for (var key in expected) {
var value = expected[key];
var type = key;
if (type === 'DECIMAL') {
type = type + '(3,3)';
} else if (/binary|char/i.test(type)) {
type = type + '(' + value.length + ')';
} else if (/bit/i.test(type)) {
type = type + '(' + (value.length * 8) + ')';
}
var escaped = connection.escape(value);
tests.forEach(function(test, index) {
var escaped = connection.escape(test.insert);
schema.push('`' + key + '` ' + type + ',');
inserts.push('`' + key + '` = ' + escaped);
}
test.columnName = test.type + '_' + index;
connection.query([
'CREATE TEMPORARY TABLE `type_casting` (',
schema.push('`' + test.columnName + '` ' + test.type + ',');
inserts.push('`' + test.columnName + '` = ' + escaped);
});
var createTable = [
'CREATE TEMPORARY TABLE `' + table + '` (',
'`id` int(11) unsigned NOT NULL AUTO_INCREMENT,',

@@ -62,6 +60,8 @@ ].concat(schema).concat([

') ENGINE=InnoDB DEFAULT CHARSET=utf8'
]).join('\n'));
]).join('\n');
connection.query('INSERT INTO type_casting SET' + inserts.join(',\n'));
connection.query(createTable);
connection.query('INSERT INTO ' + table + ' SET' + inserts.join(',\n'));
var row;

@@ -77,16 +77,22 @@ connection.query('SELECT * FROM type_casting', function(err, rows) {

process.on('exit', function() {
for (var key in expected) {
var expectedValue = expected[key];
var actualValue = row[key];
tests.forEach(function(test) {
var expected = test.expect || test.insert;
var got = row[test.columnName];
if (expectedValue instanceof Date) {
expectedValue = Number(expectedValue);
actualValue = Number(actualValue);
} else if (Buffer.isBuffer(expectedValue)) {
expectedValue = Array.prototype.slice.call(expectedValue)+'';
actualValue = Array.prototype.slice.call(actualValue)+'';
if (expected instanceof Date) {
assert.equal(got instanceof Date, true, test.type);
expected = String(expected);
got = String(got);
} else if (Buffer.isBuffer(expected)) {
assert.equal(Buffer.isBuffer(got), true, test.type);
expected = String(Array.prototype.slice.call(expected));
got = String(Array.prototype.slice.call(got));
}
assert.strictEqual(actualValue, expectedValue, key + ': ' + actualValue + ' !== ' + expectedValue);
}
var message =
'got: "' + got + '" expected: "' + expected + '" test: ' + test.type + '';
assert.strictEqual(expected, got, message);
});
});

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

'objects function properties are ignored': function() {
assert.equal(SqlString.escape({a: 'b', c: function() {}}), "`a` = 'b'");
},
'nested objects are cast to strings': function() {

@@ -30,0 +34,0 @@ assert.equal(SqlString.escape({a: {nested: true}}), "`a` = '[object Object]'");

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc