Comparing version 1.5.1 to 1.5.2
@@ -0,7 +1,17 @@ | ||
1.5.2 (06/02/2018) | ||
- perf: Store Compiled Packet Parsers in a global | ||
cache #722, #723 | ||
- Improve performance of removing connections from | ||
pools #720 | ||
- use source parameters types with execute, fix | ||
crash when parameter is undefined #718, #705 | ||
- PromisePool to always use the specified promises | ||
library #697 | ||
1.5.1 (19/11/2017) | ||
- Fix empty buffer incorrectly returned instead of | ||
- Fix empty buffer incorrectly returned instead of | ||
NULL value #668, #671 | ||
- promise wrapper: pass sqlMessage from original | ||
- promise wrapper: pass sqlMessage from original | ||
error #682, #678 | ||
1.5.0 (13/11/2017) | ||
@@ -11,6 +21,6 @@ - Added sqlMessage to Error callback object #665 | ||
as Mysql specifies it | ||
- Remove destroyed promise pool connections from | ||
- Remove destroyed promise pool connections from | ||
pool #674, #672 | ||
- Expose escape & format methods on connection pool #669, #663 | ||
- Support fractional seconds variable precision for | ||
- Support fractional seconds variable precision for | ||
the temporal types #660, #659 | ||
@@ -17,0 +27,0 @@ - fix null values breaking typeCast behaviour #652 |
@@ -5,2 +5,3 @@ var SqlString = require('sqlstring'); | ||
var ConnectionConfig = require('./lib/connection_config.js'); | ||
var parserCache = require("./lib/parsers/parser_cache"); | ||
@@ -65,1 +66,9 @@ module.exports.createConnection = function(opts) { | ||
}); | ||
exports.setMaxParserCache = function (max) { | ||
parserCache.setMaxCache(max); | ||
}; | ||
exports.clearParserCache = function () { | ||
parserCache.clearCache(); | ||
}; |
@@ -9,3 +9,3 @@ var util = require('util'); | ||
var compileParser = require('../compile_binary_parser.js'); | ||
var getBinaryParser = require('../parsers/binary_parser.js'); | ||
@@ -37,9 +37,3 @@ function Execute(options, callback) { | ||
Execute.prototype.buildParserFromFields = function(fields, connection) { | ||
var parserKey = connection.keyFromFields(fields, this.options); | ||
var parser = connection.binaryProtocolParsers[parserKey]; | ||
if (!parser) { | ||
parser = compileParser(fields, this.options, connection.config); | ||
connection.binaryProtocolParsers[parserKey] = parser; | ||
} | ||
return parser; | ||
return getBinaryParser(fields, this.options, connection.config); | ||
}; | ||
@@ -55,3 +49,13 @@ | ||
); | ||
connection.writePacket(executePacket.toPacket(1)); | ||
//For reasons why this try-catch is here, please see | ||
// https://github.com/sidorares/node-mysql2/pull/689 | ||
//For additional discussion, see | ||
// 1. https://github.com/sidorares/node-mysql2/issues/493 | ||
// 2. https://github.com/sidorares/node-mysql2/issues/187 | ||
// 3. https://github.com/sidorares/node-mysql2/issues/480 | ||
try { | ||
connection.writePacket(executePacket.toPacket(1)); | ||
} catch (error) { | ||
this.onResult(error) | ||
} | ||
return Execute.prototype.resultsetHeader; | ||
@@ -58,0 +62,0 @@ }; |
@@ -10,3 +10,3 @@ var fs = require('fs'); | ||
var Packets = require('../packets/index.js'); | ||
var compileParser = require('../compile_text_parser.js'); | ||
var getTextParser = require('../parsers/text_parser.js'); | ||
var ServerStatus = require('../constants/server_status.js'); | ||
@@ -199,11 +199,6 @@ var CharsetToEncoding = require('../constants/charset_encodings.js'); | ||
// last field received | ||
if (this._receivedFieldsCount == this._fieldCount) { | ||
if (this._receivedFieldsCount === this._fieldCount) { | ||
var fields = this._fields[this._resultIndex]; | ||
this.emit('fields', fields); | ||
var parserKey = connection.keyFromFields(fields, this.options); | ||
this._rowParser = connection.textProtocolParsers[parserKey]; | ||
if (!this._rowParser) { | ||
this._rowParser = compileParser(fields, this.options, connection.config); | ||
connection.textProtocolParsers[parserKey] = this._rowParser; | ||
} | ||
this._rowParser = getTextParser(fields, this.options, connection.config); | ||
return Query.prototype.fieldsEOF; | ||
@@ -210,0 +205,0 @@ } |
@@ -61,15 +61,2 @@ var Net = require('net'); | ||
// TODO: make it lru cache | ||
// https://github.com/mercadolibre/node-simple-lru-cache | ||
// or https://github.com/rsms/js-lru | ||
// or https://github.com/monsur/jscache | ||
// or https://github.com/isaacs/node-lru-cache | ||
// | ||
// key is field.name + ':' + field.columnType + ':' field.flags + '/' | ||
this.textProtocolParsers = {}; | ||
// TODO: not sure if cache should be separate (same key as with textProtocolParsers) | ||
// or part of prepared statements cache (key is sql query) | ||
this.binaryProtocolParsers = {}; | ||
this.serverCapabilityFlags = 0; | ||
@@ -643,21 +630,2 @@ this.authorized = false; | ||
Connection.prototype.keyFromFields = function keyFromFields(fields, options) { | ||
var res = | ||
typeof options.nestTables + | ||
'/' + | ||
options.nestTables + | ||
'/' + | ||
options.rowsAsArray + | ||
options.supportBigNumbers + | ||
'/' + | ||
options.bigNumberStrings + | ||
'/' + | ||
typeof options.typeCast; | ||
for (var i = 0; i < fields.length; ++i) { | ||
res += | ||
'/' + fields[i].name + ':' + fields[i].columnType + ':' + fields[i].flags; | ||
} | ||
return res; | ||
}; | ||
Connection.statementKey = function(options) { | ||
@@ -720,2 +688,14 @@ return ( | ||
// check for values containing undefined | ||
if (options.values) { | ||
options.values.forEach(function(val) { | ||
if (val === undefined) { | ||
throw new TypeError('Bind parameters must not contain undefined. To pass SQL NULL specify JS null'); | ||
} | ||
if (typeof val === 'function') { | ||
throw new TypeError('Bind parameters must not contain function(s). To pass the body of a function as a string call .toString() first') | ||
} | ||
}); | ||
} | ||
var executeCommand = new Commands.Execute(options, cb); | ||
@@ -722,0 +702,0 @@ var prepareCommand = new Commands.Prepare(options, function(err, stmt) { |
@@ -14,13 +14,66 @@ var Buffer = require('safe-buffer').Buffer; | ||
var pad = '000000000000'; | ||
function leftPad(num, value) { | ||
var s = value.toString(); | ||
// if we don't need to pad | ||
if (s.length >= num) { | ||
return s; | ||
function isJSON(value) { | ||
return Array.isArray(value) || | ||
value.constructor === Object || | ||
(typeof value.toJSON === 'function' && !Buffer.isBuffer(value)); | ||
} | ||
/** | ||
* Converts a value to an object describing type, String/Buffer representation and length | ||
* @param {*} value | ||
*/ | ||
function toParameter(value, encoding) { | ||
var type = Types.VAR_STRING; | ||
var length; | ||
var writer = function (value) { | ||
return Packet.prototype.writeLengthCodedString.call(this, value, encoding) | ||
} | ||
if (value !== null) { | ||
switch (typeof value) { | ||
case 'undefined': | ||
throw new TypeError('Bind parameters must not contain undefined'); | ||
case 'number': | ||
type = Types.DOUBLE; | ||
length = 8; | ||
writer = Packet.prototype.writeDouble; | ||
break; | ||
case 'boolean': | ||
value = value | 0; | ||
type = Types.TINY; | ||
length = 1; | ||
writer = Packet.prototype.writeInt8; | ||
break; | ||
case 'object': | ||
if (Object.prototype.toString.call(value) == '[object Date]') { | ||
type = Types.DATETIME; | ||
length = 12; | ||
writer = Packet.prototype.writeDate | ||
} else if (isJSON(value)) { | ||
value = JSON.stringify(value); | ||
type = Types.JSON; | ||
} else if (Buffer.isBuffer(value)) { | ||
length = Packet.lengthCodedNumberLength(value.length) + value.length; | ||
writer = Packet.prototype.writeLengthCodedBuffer | ||
} | ||
break; | ||
default: | ||
value = value.toString(); | ||
} | ||
return (pad + s).slice(-num); | ||
} else { | ||
value = '' | ||
type = Types.NULL; | ||
} | ||
if (!length) { | ||
length = Packet.lengthCodedStringLength(value, encoding); | ||
} | ||
return { value, type, length, writer }; | ||
} | ||
Execute.prototype.toPacket = function() { | ||
var self = this; | ||
// TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?) | ||
@@ -36,2 +89,3 @@ // and copy + reallocate if not enough | ||
var length = 14; | ||
var parameters; | ||
if (this.parameters && this.parameters.length > 0) { | ||
@@ -41,25 +95,8 @@ length += Math.floor((this.parameters.length + 7) / 8); | ||
length += 2 * this.parameters.length; // type byte for each parameter if new-params-bound-flag is set | ||
for (i = 0; i < this.parameters.length; i++) { | ||
if (this.parameters[i] !== null) { | ||
if ( | ||
Object.prototype.toString.call(this.parameters[i]) == '[object Date]' | ||
) { | ||
var d = this.parameters[i]; | ||
// TODO: move to asMysqlDateTime() | ||
this.parameters[i] = | ||
[d.getFullYear(), d.getMonth() + 1, d.getDate()].join('-') + | ||
' ' + | ||
[d.getHours(), d.getMinutes(), d.getSeconds()].join(':') + | ||
'.' + leftPad(3, d.getMilliseconds()) | ||
; | ||
} | ||
if (Buffer.isBuffer(this.parameters[i])) { | ||
length += Packet.lengthCodedNumberLength(this.parameters[i].length); | ||
length += this.parameters[i].length; | ||
} else { | ||
var str = this.parameters[i].toString(); | ||
length += Packet.lengthCodedStringLength(str, this.encoding); | ||
} | ||
} | ||
} | ||
parameters = this.parameters.map(function (value) { | ||
return toParameter(value, self.encoding); | ||
}); | ||
length += parameters.reduce(function (accumulator, parameter) { | ||
return accumulator + parameter.length; | ||
}, 0); | ||
} | ||
@@ -74,7 +111,7 @@ | ||
packet.writeInt32(1); // iteration-count, always 1 | ||
if (this.parameters && this.parameters.length > 0) { | ||
if (parameters) { | ||
var bitmap = 0; | ||
var bitValue = 1; | ||
for (i = 0; i < this.parameters.length; i++) { | ||
if (this.parameters[i] === null) { | ||
parameters.forEach(function (parameter) { | ||
if (parameter.type === Types.NULL) { | ||
bitmap += bitValue; | ||
@@ -88,3 +125,3 @@ } | ||
} | ||
} | ||
}); | ||
if (bitValue != 1) { | ||
@@ -99,23 +136,14 @@ packet.writeInt8(bitmap); | ||
// TODO: don't typecast always to sting, use parameters type | ||
for (i = 0; i < this.parameters.length; i++) { | ||
if (this.parameters[i] !== null) { | ||
packet.writeInt16(Types.VAR_STRING); | ||
} else { | ||
packet.writeInt16(Types.NULL); | ||
} | ||
} | ||
// Write parameter types | ||
parameters.forEach(function (parameter) { | ||
packet.writeInt8(parameter.type); // field type | ||
packet.writeInt8(0); // parameter flag | ||
}); | ||
for (i = 0; i < this.parameters.length; i++) { | ||
if (this.parameters[i] !== null) { | ||
if (Buffer.isBuffer(this.parameters[i])) { | ||
packet.writeLengthCodedBuffer(this.parameters[i]); | ||
} else { | ||
packet.writeLengthCodedString( | ||
this.parameters[i].toString(), | ||
this.encoding | ||
); | ||
} | ||
// Write parameter values | ||
parameters.forEach(function (parameter) { | ||
if (parameter.type !== Types.NULL) { | ||
parameter.writer.call(packet, parameter.value) | ||
} | ||
} | ||
}); | ||
} | ||
@@ -122,0 +150,0 @@ return packet; |
@@ -763,2 +763,7 @@ var ErrorCodeToName = require('../constants/errors.js'); | ||
Packet.prototype.writeDouble = function(n) { | ||
this.buffer.writeDoubleLE(n, this.offset); | ||
this.offset += 8; | ||
} | ||
Packet.prototype.writeBuffer = function(b) { | ||
@@ -843,2 +848,14 @@ b.copy(this.buffer, this.offset); | ||
Packet.prototype.writeDate = function(d) { | ||
this.buffer.writeUInt8(11, this.offset); | ||
this.buffer.writeUInt16LE(d.getFullYear(), this.offset + 1); | ||
this.buffer.writeUInt8(d.getMonth() + 1, this.offset + 3); | ||
this.buffer.writeUInt8(d.getDate(), this.offset + 4); | ||
this.buffer.writeUInt8(d.getHours(), this.offset + 5); | ||
this.buffer.writeUInt8(d.getMinutes(), this.offset + 6); | ||
this.buffer.writeUInt8(d.getSeconds(), this.offset + 7); | ||
this.buffer.writeUInt32LE(d.getMilliseconds() * 1000, this.offset + 8); | ||
this.offset += 12; | ||
} | ||
Packet.prototype.writeHeader = function(sequenceId) { | ||
@@ -845,0 +862,0 @@ var offset = this.offset; |
@@ -220,15 +220,8 @@ var mysql = require('../index.js'); | ||
var len = queue.length; | ||
if (len) { | ||
if (queue.get(len - 1) === connection) { | ||
queue.pop(); | ||
} else { | ||
for (; --len; ) { | ||
if (queue.get(0) === connection) { | ||
queue.shift(); | ||
break; | ||
} | ||
queue.push(queue.shift()); | ||
} | ||
for (var i = 0; i < len; i++) { | ||
if (queue.get(i) === connection) { | ||
queue.removeOne(i); | ||
break; | ||
} | ||
} | ||
} |
{ | ||
"name": "mysql2", | ||
"version": "1.5.1", | ||
"version": "1.5.2", | ||
"description": "fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS", | ||
@@ -52,3 +52,3 @@ "main": "index.js", | ||
"iconv-lite": "^0.4.18", | ||
"long": "^3.2.0", | ||
"long": "^4.0.0", | ||
"lru-cache": "^4.1.1", | ||
@@ -72,3 +72,3 @@ "named-placeholders": "1.1.1", | ||
"is-async-supported": "^1.2.0", | ||
"lint-staged": "^5.0.0", | ||
"lint-staged": "^6.0.0", | ||
"portfinder": "^1.0.10", | ||
@@ -75,0 +75,0 @@ "prettier": "^1.3.1", |
@@ -359,3 +359,3 @@ var core = require('./index.js'); | ||
return new Promise(function(resolve, reject) { | ||
return new this.Promise(function(resolve, reject) { | ||
corePool.execute(sql, values, makeDoneCb(resolve, reject, localErr)); | ||
@@ -368,3 +368,3 @@ }); | ||
const localErr = new Error(); | ||
return new Promise(function(resolve, reject) { | ||
return new this.Promise(function(resolve, reject) { | ||
corePool.end(function(err) { | ||
@@ -371,0 +371,0 @@ if (err) { |
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
339816
67
8742
+ Addedlong@4.0.0(transitive)
- Removedlong@3.2.0(transitive)
Updatedlong@^4.0.0