Comparing version 0.8.18 to 0.8.19
@@ -36,3 +36,3 @@ var common = require('../test/common'); | ||
function benchmarkSelects(n, cb) { | ||
var numSelects = 100000; | ||
var numSelects = 1000; | ||
var start = process.hrtime(); | ||
@@ -39,0 +39,0 @@ benchmarkSelect(numSelects, function(rowsPerQuery) { |
@@ -15,2 +15,3 @@ var assert = require('assert'); | ||
db.query(sql).on('end', function(err, res) { | ||
//db.execute(sql).on('end', function(err, res) { | ||
left--; | ||
@@ -17,0 +18,0 @@ if (left % 1000 === 0) |
@@ -55,6 +55,6 @@ var mysql = require('../index.js'); | ||
decimals: 0 | ||
}], ['12345'], 1); | ||
}], ['12345'], 10000); | ||
var server = mysql.createServer(); | ||
server.listen('/tmp/mybench3.sock'); | ||
server.listen('/tmp/mybench4.sock'); | ||
server.on('connection', function(conn) { | ||
@@ -61,0 +61,0 @@ conn.serverHandshake({ |
@@ -1,5 +0,126 @@ | ||
var mysql = require('../test/common').createConnection(); | ||
var mysql = require('../test/common').createConnection({multipleStatements: true}); | ||
var assert = require('assert'); | ||
mysql.query('CREATE TEMPORARY TABLE no_rows (test int)'); | ||
mysql.query('CREATE TEMPORARY TABLE some_rows (test int)'); | ||
mysql.query('INSERT INTO some_rows values(0)'); | ||
mysql.query('INSERT INTO some_rows values(42)'); | ||
mysql.query('INSERT INTO some_rows values(314149)'); | ||
mysql.execute("select cast(9223372036854775807) as unsigned v", function(err, rows, fields) { | ||
console.log(rows, fields); | ||
}); | ||
var clone = function(obj) { return JSON.parse(JSON.stringify(obj)); }; | ||
var rs1 = { | ||
affectedRows: 0, | ||
fieldCount: 0, | ||
insertId: 0, | ||
serverStatus: 10, | ||
warningStatus: 0 | ||
}; | ||
var rs2 = clone(rs1); | ||
rs2.serverStatus = 2; | ||
var twoInsertResult = [[rs1, rs2], [undefined, undefined], 2]; | ||
var select1 = [{"1":"1"}]; | ||
var select2 = [{"2":"2"}]; | ||
var fields1 = [{ | ||
catalog: "def", | ||
characterSet: 63, | ||
columnLength: 1, | ||
columnType: 8, | ||
decimals: 0, | ||
flags: 129, | ||
name: "1", | ||
orgName: "", | ||
orgTable: "", | ||
schema: "", | ||
table: "" | ||
}]; | ||
var nr_fields = [{ | ||
catalog: "def", | ||
characterSet: 63, | ||
columnLength: 11, | ||
columnType: 3, | ||
decimals: 0, | ||
flags: 0, | ||
name: "test", | ||
orgName: "test", | ||
orgTable: "no_rows", | ||
schema: "test", | ||
table: "no_rows" | ||
}]; | ||
var sr_fields = clone(nr_fields); | ||
sr_fields[0].orgTable = "some_rows"; | ||
sr_fields[0].table = "some_rows"; | ||
var select3 = [{"test":0},{"test":42},{"test":314149}]; | ||
var fields2 = clone(fields1); | ||
fields2[0].name = "2"; | ||
var tests = [ | ||
["SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT; SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;", twoInsertResult], | ||
["/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;", twoInsertResult], // issue #26 | ||
["set @a = 1", [rs2, undefined, 1]], // one insert result | ||
["set @a = 1; set @b = 2", twoInsertResult], | ||
["select 1; select 2", [[select1,select2],[fields1,fields2], 2]], | ||
["set @a = 1; select 1", [[rs1, select1], [undefined, fields1], 2]], | ||
["select 1; set @a = 1", [[select1, rs2], [fields1, undefined], 2]], | ||
["select * from no_rows", [[], nr_fields, 1]], // select 0 rows" | ||
["set @a = 1; select * from no_rows", [[rs1, []], [undefined, nr_fields], 2]], // insert + select 0 rows | ||
["select * from no_rows; set @a = 1", [[[], rs2], [nr_fields, undefined], 2]], // select 0 rows + insert | ||
["set @a = 1; select * from some_rows", [[rs1, select3],[undefined,sr_fields],2]], // insert + select 3 rows | ||
["select * from some_rows; set @a = 1", [[select3,rs2],[sr_fields,undefined],2]] // select 3 rows + insert | ||
]; | ||
// TODO: tests with error in the query with different index | ||
function do_test(testIndex) { | ||
var entry = tests[testIndex]; | ||
var sql = entry[0]; | ||
var expectation = entry[1]; | ||
mysql.query(sql, function(err, _rows, _columns, _numResults) { | ||
if (err) return; //process.exit(1); | ||
assert.deepEqual(expectation, [_rows, _columns, _numResults]); | ||
//assert.deepEqual(expectation[0], _rows); | ||
//assert.deepEqual(expectation[1], _columns); | ||
//assert.deepEqual(expectation[2], _numResults); | ||
var q = mysql.query(sql); | ||
var resIndex = 0; | ||
var rowIndex = 0; | ||
function checkRow(row, index) { | ||
if (_numResults == 1) { | ||
assert.equal(index, 0); | ||
if (row.constructor.name == 'ResultSetHeader') | ||
assert.deepEqual(_rows, row); | ||
else | ||
assert.deepEqual(_rows[rowIndex], row); | ||
} else { | ||
if (resIndex != index) { | ||
rowIndex = 0; | ||
resIndex = index; | ||
} | ||
if (row.constructor.name == 'ResultSetHeader') | ||
assert.deepEqual(_rows[index], row); | ||
else | ||
assert.deepEqual(_rows[index][rowIndex], row); | ||
} | ||
rowIndex++; | ||
} | ||
function checkFields(fields, index) { | ||
if (_numResults == 1) { | ||
assert.equal(index, 0); | ||
assert.deepEqual(_columns, fields); | ||
} | ||
else | ||
assert.deepEqual(_columns[index], fields); | ||
} | ||
q.on('result', checkRow); | ||
q.on('fields', checkFields); | ||
q.on('end', function() { | ||
if (testIndex + 1 < tests.length) | ||
do_test(testIndex + 1); | ||
else { | ||
mysql.end(); | ||
} | ||
}); | ||
}); | ||
} | ||
do_test(0); |
@@ -6,5 +6,6 @@ var Command = require('./command'); | ||
function ClientHandshake() | ||
function ClientHandshake(clientFlags) | ||
{ | ||
this.handshake = null; | ||
this.clientFlags = clientFlags; | ||
Command.call(this); | ||
@@ -21,4 +22,4 @@ } | ||
// should be something like { ssl: true, sslRequest: true } for sslRequest packet | ||
// and { ..., ssl: true } for ghandshakeReply packet | ||
var sslRequest = new Packets.HandshakeResponse({ ssl: true }); | ||
// and { ..., ssl: true } for handshakeReply packet | ||
var sslRequest = new Packets.HandshakeResponse({ ssl: true, flags: this.clientFlags }); | ||
connection.writePacket(sslRequest.toPacket(1)); | ||
@@ -36,3 +37,3 @@ }; | ||
}); | ||
connection.writePacket(handshakeResponse.toPacket(packetIndex)); | ||
connection.writePacket(handshakeResponse.toPacket(packetIndex, this.clientFlags)); | ||
}; | ||
@@ -39,0 +40,0 @@ |
var Command = require('./command'); | ||
var Packets = require('../packets/index.js'); | ||
var util = require('util'); | ||
var compileParser = require('../compile_text_parser'); | ||
var compileParser = require('../compile_text_parser.js'); | ||
var ServerStatus = require('../constants/server_status.js'); | ||
@@ -11,8 +12,8 @@ function Query(sql, callback) | ||
this.onResult = callback; // TODO check felixge multi-result api | ||
this.fieldCount = 0; | ||
this.insertId = 0; | ||
this.fields = []; | ||
this.rows = []; | ||
this.rowParser = null; | ||
this._fieldCount = 0; | ||
this._rowParser = null; | ||
this._fields = []; | ||
this._rows = []; | ||
this._receivedFieldsCount = 0; | ||
this._resultIndex = 0; | ||
} | ||
@@ -27,13 +28,32 @@ util.inherits(Query, Command); | ||
Query.prototype.done = function() { | ||
if (this.onResult) { | ||
if (this._resultIndex === 0) { | ||
this.onResult(null, this._rows[0], this._fields[0], this._resultIndex+1); | ||
} else { | ||
this.onResult(null, this._rows, this._fields, this._resultIndex+1); | ||
} | ||
} | ||
return null; | ||
}; | ||
Query.prototype.resultsetHeader = function(packet) { | ||
var rs = new Packets.ResultSetHeader(packet); | ||
this.fieldCount = rs.fieldCount; | ||
this.affectedRows = rs.affectedRows; | ||
this.insertId = rs.insertId; | ||
if (this.fieldCount === 0) { | ||
if (this.onResult) | ||
this.onResult(null, this, []); | ||
return null; | ||
this._fieldCount = rs.fieldCount; | ||
if (this._fieldCount === 0) { | ||
this._rows.push(rs); | ||
this._fields.push(void(0)); | ||
this.emit('result', rs, this._resultIndex); | ||
this.emit('fields', void(0), this._resultIndex); | ||
if (rs.serverStatus & ServerStatus.SERVER_MORE_RESULTS_EXISTS) { | ||
this._resultIndex++; | ||
return Query.prototype.resultsetHeader; | ||
} | ||
return this.done(); | ||
} | ||
this._receivedFieldsCount = 0; | ||
this._rows.push([]); | ||
this._fields.push([]); | ||
return Query.prototype.readField; | ||
@@ -51,16 +71,23 @@ }; | ||
Query.prototype.readField = function(packet, connection) { | ||
this._receivedFieldsCount++; | ||
// allow to set fields in advance. If already set, ignore | ||
if (this.fields.length != this.fieldCount) { | ||
// Often there is much more data in the column definition than in the row itself | ||
// If you set manually _fields[0] to array of ColumnDefinition's (from previous call) | ||
// you can 'cache' result of parsing. Field packets still received, but ignored in that case | ||
// this s the reason _receivedFieldsCount exist (otherwise we could just use current length of fields array) | ||
if (this._fields[this._resultIndex].length != this._fieldCount) { | ||
var field = new Packets.ColumnDefinition(packet); | ||
this.fields.push(field); | ||
this._fields[this._resultIndex].push(field); | ||
} | ||
if (this._receivedFieldsCount == this.fieldCount) { | ||
var parserKey = getFieldsKey(this.fields); | ||
// try cached first | ||
// last field received | ||
if (this._receivedFieldsCount == this._fieldCount) { | ||
var fields = this._fields[this._resultIndex]; | ||
this.emit('fields', fields, this._resultIndex); | ||
var parserKey = getFieldsKey(fields); | ||
this.rowParser = connection.textProtocolParsers[parserKey]; | ||
if (!this.rowParser) { | ||
this.rowParser = compileParser(this.fields); | ||
this.rowParser = compileParser(fields); | ||
connection.textProtocolParsers[parserKey] = this.rowParser; | ||
@@ -83,39 +110,17 @@ } | ||
if (packet.isEOF()) { | ||
if (this.onResult) | ||
this.onResult(null, this.rows, this.fields); | ||
return null; | ||
var status = packet.eofStatusFlags(); | ||
var moreResults = packet.eofStatusFlags() & ServerStatus.SERVER_MORE_RESULTS_EXISTS; | ||
if (moreResults) { | ||
this._resultIndex++; | ||
return Query.prototype.resultsetHeader; | ||
} | ||
return this.done(); | ||
} | ||
if (this.rowParser) { | ||
// compiled version: | ||
// TODO: compile (and assign to this.next) whole command handler, not just row constructor+parser? | ||
var row = new this.rowParser(packet); | ||
if (this.onResult) | ||
this.rows.push(row); | ||
else | ||
this.emit('result', row); | ||
return Query.prototype.row; | ||
} | ||
var row = new this.rowParser(packet); | ||
if (this.onResult) | ||
this._rows[this._resultIndex].push(row); | ||
else | ||
this.emit('result', row, this._resultIndex); | ||
// non-compiled | ||
var row = Packets.TextRow.fromPacket(packet); | ||
// TODO: here we'll have dynamically pre-compiled and cached row parser | ||
if (true) // TODO: think of API to store raw copulns array (most probably connection options flags) | ||
{ | ||
var r = {}; | ||
for (var i = 0; i < row.columns.length; ++i) | ||
{ | ||
var name = this.fields[i].name; | ||
r[name] = row.columns[i]; | ||
} | ||
if (this.onResult) | ||
this.rows.push(r); | ||
else | ||
this.emit('result', r); | ||
} else { | ||
if (this.onResult) | ||
this.rows.push(row.columns); | ||
else | ||
this.emit('result', row.columns); | ||
} | ||
return Query.prototype.row; | ||
@@ -122,0 +127,0 @@ }; |
@@ -58,3 +58,3 @@ var urlParse = require('url').parse; | ||
flags |= ClientConstants["CLIENT_" + default_flags[i]] || 0x0; | ||
flags |= ClientConstants[default_flags[i]] || 0x0; | ||
} | ||
@@ -66,3 +66,3 @@ // add user flags unless already already added | ||
flags |= ClientConstants["CLIENT_" + user_flags[i]] || 0x0; | ||
flags |= ClientConstants[user_flags[i]] || 0x0; | ||
} | ||
@@ -69,0 +69,0 @@ |
@@ -81,4 +81,5 @@ var net = require('net'); | ||
}); | ||
if (!this.config.isServer) | ||
this.addCommand(new Commands.ClientHandshake()); | ||
if (!this.config.isServer) { | ||
this.addCommand(new Commands.ClientHandshake(this.config.clientFlags)); | ||
} | ||
} | ||
@@ -85,0 +86,0 @@ util.inherits(Connection, EventEmitter); |
@@ -55,12 +55,13 @@ var ClientConstants = require('../constants/client'); | ||
HandshakeResponse.prototype.toPacket = function(packetIndex) | ||
HandshakeResponse.prototype.toPacket = function(packetIndex, flags) | ||
{ | ||
// TODO: move flags to command? | ||
/* | ||
var flags = | ||
ClientConstants.LONG_PASSWORD | ClientConstants.FOUND_ROWS | ClientConstants.LONG_FLAG | | ||
ClientConstants.LONG_PASSWORD | ClientConstants.FOUND_ROWS | ClientConstants.LONG_FLAG | ClientConstants.MULTI_STATEMENTS | | ||
ClientConstants.CONNECT_WITH_DB | ClientConstants.ODBC | ClientConstants.MULTI_RESULTS | | ||
ClientConstants.SECURE_CONNECTION | ClientConstants.RESERVED | ClientConstants.TRANSACTIONS | | ||
ClientConstants.IGNORE_SIGPIPE | ClientConstants.PROTOCOL_41 | ClientConstants.IGNORE_SPACE | ClientConstants.LOCAL_FILES; | ||
this.clientFlags = flags; | ||
this.characterSet = Charsets.UTF8_GENERAL_CI; | ||
*/ | ||
var clientFlags = flags; | ||
var characterSet = Charsets.UTF8_GENERAL_CI; | ||
@@ -82,5 +83,5 @@ var length = 36; | ||
packet.writeInt32(this.clientFlags); | ||
packet.writeInt32(clientFlags); | ||
packet.writeInt32(0); // max packet size. todo: move to config | ||
packet.writeInt8(this.characterSet); | ||
packet.writeInt8(characterSet); | ||
packet.skip(23); | ||
@@ -87,0 +88,0 @@ if (!this.ssl) { |
@@ -97,2 +97,10 @@ //var BigNumber = require("bignumber.js"); | ||
Packet.prototype.eofStatusFlags = function() { | ||
return this.buffer.readInt16LE(this.offset + 3); | ||
}; | ||
Packet.prototype.eofWarningCount = function() { | ||
return this.buffer.readInt16LE(this.offset + 1); | ||
}; | ||
Packet.prototype.readLengthCodedNumber = function() { | ||
@@ -99,0 +107,0 @@ var byte1 = this.readInt8(); |
{ | ||
"name": "mysql2", | ||
"version": "0.8.18", | ||
"version": "0.8.19", | ||
"description": "fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -1,2 +0,2 @@ | ||
module.exports.createConnection = function(callback) { | ||
module.exports.createConnection = function(args, callback) { | ||
// hrtime polyfill for old node versions: | ||
@@ -49,2 +49,3 @@ if (!process.hrtime) | ||
database: 'test', | ||
multipleStatements: args ? args.multipleStatements : false, | ||
port: process.env.MYSQL_PORT || 3306 | ||
@@ -51,0 +52,0 @@ }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
208555
99
4885