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

mariadb

Package Overview
Dependencies
Maintainers
3
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mariadb - npm Package Compare versions

Comparing version 3.0.0 to 3.0.1

lib/command-parameter.js

160

lib/cluster.js

@@ -55,12 +55,10 @@ 'use strict';

end() {
const cluster = this;
this.#cachedPatterns = {};
const poolEndPromise = [];
Object.keys(this.#nodes).forEach(
function (pool) {
const res = this.#nodes[pool].end();
if (res) poolEndPromise.push();
delete this.#nodes[pool];
}.bind(this)
);
Object.keys(this.#nodes).forEach((pool) => {
const res = cluster.#nodes[pool].end();
if (res) poolEndPromise.push(res);
});
this.#nodes = null;
return Promise.all(poolEndPromise);

@@ -121,6 +119,7 @@ }

* @param lastError last error
* @param remainingRetry remaining possible retry
* @return {Promise}
* @private
*/
_getConnection(pattern, selector, avoidNodeKey, lastError) {
_getConnection(pattern, selector, remainingRetry, avoidNodeKey, lastError) {
const matchingNodeList = this._matchingNodes(pattern || /^/);

@@ -141,3 +140,5 @@

const retry = this._getConnection.bind(this, pattern, selector);
if (remainingRetry === undefined) remainingRetry = matchingNodeList.length;
const retry = --remainingRetry >= 0 ? this._getConnection.bind(this, pattern, selector, remainingRetry) : null;
try {

@@ -232,5 +233,4 @@ const nodeKey = this._selectPool(matchingNodeList, selector, avoidNodeKey);

const selector = selectorParam || this.#opts.defaultSelector;
let retry = 0;
let selectorFct;
let nodeKey;
switch (selector) {

@@ -253,10 +253,23 @@ case 'RR':

nodeKey = selectorFct(nodeList, retry);
let nodeIdx = 0;
let nodeKey = selectorFct(nodeList, nodeIdx);
// first loop : search for node not blacklisted AND not the avoided key
while (
(avoidNodeKey === nodeKey || this.#nodes[nodeKey].blacklistedUntil > Date.now()) &&
retry < nodeList.length - 1
(avoidNodeKey === nodeKey ||
(this.#nodes[nodeKey].blacklistedUntil && this.#nodes[nodeKey].blacklistedUntil > Date.now())) &&
nodeIdx < nodeList.length - 1
) {
retry++;
nodeKey = selectorFct(nodeList, retry);
nodeIdx++;
nodeKey = selectorFct(nodeList, nodeIdx);
}
if (avoidNodeKey === nodeKey) {
// second loop, search even in blacklisted node in order to choose a different node than to be avoided
nodeIdx = 0;
while (avoidNodeKey === nodeKey && nodeIdx < nodeList.length - 1) {
nodeIdx++;
nodeKey = selectorFct(nodeList, nodeIdx);
}
}
return nodeKey;

@@ -275,2 +288,3 @@ }

_handleConnectionError(nodeList, nodeKey, retryFct) {
const cluster = this;
const node = this.#nodes[nodeKey];

@@ -280,34 +294,30 @@ return node

.then((conn) => {
node.blacklistedUntil = null;
node.errorCount = 0;
return Promise.resolve(conn);
})
.catch(
function (err) {
node.errorCount = node.errorCount ? node.errorCount + 1 : 1;
node.blacklistedUntil = Date.now() + this.#opts.restoreNodeTimeout;
if (
this.#opts.removeNodeErrorCount &&
node.errorCount >= this.#opts.removeNodeErrorCount &&
this.#nodes[nodeKey]
) {
delete this.#nodes[nodeKey];
this.#cachedPatterns = {};
delete nodeList.lastRrIdx;
process.nextTick(
function () {
this.emit('remove', nodeKey);
}.bind(this)
);
//remove node from configuration if not already removed
node.end().catch((err) => {
// dismiss error
});
}
.catch((err) => {
node.errorCount = node.errorCount ? node.errorCount + 1 : 1;
node.blacklistedUntil = Date.now() + cluster.#opts.restoreNodeTimeout;
if (
cluster.#opts.removeNodeErrorCount &&
node.errorCount >= cluster.#opts.removeNodeErrorCount &&
cluster.#nodes[nodeKey]
) {
delete cluster.#nodes[nodeKey];
cluster.#cachedPatterns = {};
delete nodeList.lastRrIdx;
setImmediate(cluster.emit.bind(cluster, 'remove', nodeKey));
if (nodeList.length !== 0 && this.#opts.canRetry) {
return retryFct(nodeKey, err);
}
return Promise.reject(err);
}.bind(this)
);
//remove node from configuration if not already removed
node.end().catch((err) => {
// dismiss error
});
}
if (nodeList.length !== 0 && cluster.#opts.canRetry && retryFct) {
return retryFct(nodeKey, err);
}
return Promise.reject(err);
});
}

@@ -325,36 +335,34 @@

_handleConnectionCallbackError(nodeList, nodeKey, retryFct, callback) {
const cluster = this;
const node = this.#nodes[nodeKey];
node.getConnection(
function (err, conn) {
if (err) {
node.errorCount = node.errorCount ? node.errorCount + 1 : 1;
node.blacklistedUntil = Date.now() + this.#opts.restoreNodeTimeout;
if (
this.#opts.removeNodeErrorCount &&
node.errorCount >= this.#opts.removeNodeErrorCount &&
this.#nodes[nodeKey]
) {
delete this.#nodes[nodeKey];
this.#cachedPatterns = {};
delete nodeList.lastRrIdx;
process.nextTick(
function () {
this.emit('remove', nodeKey);
}.bind(this)
);
//remove node from configuration if not already removed
node.end(() => {
//dismiss error
});
if (nodeList.length === 0) return callback(err);
}
node.getConnection((err, conn) => {
if (err) {
node.errorCount = node.errorCount ? node.errorCount + 1 : 1;
node.blacklistedUntil = Date.now() + cluster.#opts.restoreNodeTimeout;
if (
cluster.#opts.removeNodeErrorCount &&
node.errorCount >= cluster.#opts.removeNodeErrorCount &&
cluster.#nodes[nodeKey]
) {
delete cluster.#nodes[nodeKey];
cluster.#cachedPatterns = {};
delete nodeList.lastRrIdx;
setImmediate(cluster.emit.bind(cluster, 'remove', nodeKey));
if (this.#opts.canRetry) return retryFct(nodeKey, err);
callback(err);
} else {
node.errorCount = 0;
callback(null, conn);
//remove node from configuration if not already removed
node.end(() => {
//dismiss error
});
}
}.bind(this)
);
if (nodeList.length !== 0 && cluster.#opts.canRetry && retryFct) {
return retryFct(nodeKey, err);
}
callback(err);
} else {
node.errorCount = 0;
callback(null, conn);
}
});
}

@@ -361,0 +369,0 @@

@@ -14,4 +14,4 @@ 'use strict';

class BatchBulk extends Parser {
constructor(resolve, reject, options, connOpts, prepare, values) {
super(resolve, reject, options, connOpts, prepare.query, values);
constructor(resolve, reject, connOpts, prepare, cmdParam) {
super(resolve, reject, connOpts, cmdParam);
this.encoder = new BinaryEncoder(this.opts);

@@ -35,2 +35,4 @@ this.binary = true;

if (this.opts.timeout) {
this.bulkPacketNo = 1;
this.sending = false;
const err = Errors.createError(

@@ -305,4 +307,2 @@ 'Cannot use timeout for Batch statement',

}
// if > max_allowed_packet, need to flush before mark
//TODO

@@ -324,3 +324,4 @@ if (!out.bufIsDataAfterMark() && !out.isMarked() && out.hasFlushed()) {

if (out.isMarked() && out.bufIsAfterMaxPacketLength()) {
// buffer > max_allowed_packet, so flush until mark, and create new packet.
// for max_allowed_packet < 16Mb
// packet length was ok at last mark, but won't with new data
out.flushBufferStopAtMark();

@@ -361,22 +362,19 @@ out.mark();

displaySql() {
if (this.opts && this.initialValues) {
if (this.sql.length > this.opts.debugLen) {
return this.sql.substring(0, this.opts.debugLen) + '...';
}
if (this.sql.length > this.opts.debugLen) {
return this.sql.substring(0, this.opts.debugLen) + '...';
}
let sqlMsg = this.sql + ' - parameters:';
sqlMsg += '[';
for (let i = 0; i < this.initialValues.length; i++) {
if (i !== 0) sqlMsg += ',';
let param = this.initialValues[i];
sqlMsg = this.logParameters(sqlMsg, param);
if (sqlMsg.length > this.opts.debugLen) {
sqlMsg = sqlMsg.substr(0, this.opts.debugLen) + '...';
break;
}
let sqlMsg = this.sql + ' - parameters:';
sqlMsg += '[';
for (let i = 0; i < this.initialValues.length; i++) {
if (i !== 0) sqlMsg += ',';
let param = this.initialValues[i];
sqlMsg = this.logParameters(sqlMsg, param);
if (sqlMsg.length > this.opts.debugLen) {
sqlMsg = sqlMsg.substr(0, this.opts.debugLen) + '...';
break;
}
sqlMsg += ']';
return sqlMsg;
}
return this.sql + ' - parameters:[]';
sqlMsg += ']';
return sqlMsg;
}

@@ -383,0 +381,0 @@

@@ -17,5 +17,5 @@ // noinspection JSBitwiseOperatorUsage

class ChangeUser extends Handshake {
constructor(options, connOpts, resolve, reject, addCommand) {
super(resolve, reject, () => {}, addCommand);
this.configAssign(connOpts, options);
constructor(cmdParam, connOpts, resolve, reject, addCommand) {
super(cmdParam, resolve, reject, () => {}, addCommand);
this.configAssign(connOpts, cmdParam.opts);
}

@@ -83,3 +83,3 @@

const encoding = this.opts.collation.charset;
const encoding = info.collation.charset;

@@ -125,4 +125,2 @@ writeParam(out, '_client_name', encoding);

this.opts = cmdOpts ? Object.assign({}, connOpts, cmdOpts) : connOpts;
this.opts.database = cmdOpts.database ? cmdOpts.database : connOpts.database;
this.opts.connectAttributes = cmdOpts.connectAttributes ? cmdOpts.connectAttributes : connOpts.connectAttributes;

@@ -129,0 +127,0 @@ if (cmdOpts.charset && typeof cmdOpts.charset === 'string') {

@@ -10,4 +10,4 @@ 'use strict';

class CachedPrepareResultPacket extends PrepareResultPacket {
constructor(statementId, parameters, columns, database, sql, placeHolderIndex, executePromise, emitter, isCallback) {
super(statementId, parameters, columns, database, sql, placeHolderIndex, executePromise, emitter, isCallback);
constructor(statementId, parameters, columns, database, sql, placeHolderIndex, executePromise, emitter, conOpts) {
super(statementId, parameters, columns, database, sql, placeHolderIndex, executePromise, emitter, conOpts);
this.cached = true;

@@ -14,0 +14,0 @@ this.use = 1;

'use strict';
const CommandParameter = require('../../command-parameter');

@@ -9,3 +10,3 @@ /**

#connExecutePromise;
constructor(statementId, parameters, columns, database, sql, placeHolderIndex, executePromise, emitter) {
constructor(statementId, parameters, columns, database, sql, placeHolderIndex, executePromise, emitter, conOpts) {
this.id = statementId;

@@ -20,5 +21,6 @@ this.parameters = parameters;

this.emitter = emitter;
this.conOpts = conOpts;
}
execute(values, opts, cb) {
execute(values, opts, cb, stack) {
let _opts = opts,

@@ -31,4 +33,5 @@ _cb = cb;

}
const promise = new Promise((resolve, reject) => this.#connExecutePromise(values, opts, this, resolve, reject));
const cmdParam = new CommandParameter(this.query, values, _opts, cb);
if (stack) cmdParam.stack = stack;
const promise = new Promise((resolve, reject) => this.#connExecutePromise(cmdParam, this, resolve, reject));
if (!_cb) {

@@ -35,0 +38,0 @@ return promise;

@@ -10,4 +10,4 @@ 'use strict';

class ClosePrepare extends Command {
constructor(resolve, reject, prepare) {
super(resolve, reject);
constructor(cmdParam, resolve, reject, prepare) {
super(cmdParam, resolve, reject);
this.prepare = prepare;

@@ -14,0 +14,0 @@ }

@@ -14,4 +14,5 @@ 'use strict';

class ColumnDef {
constructor(packet, info) {
this._stringParser = new StringParser(packet);
#stringParser;
constructor(packet, info, skipName) {
this.#stringParser = skipName ? new StringParser(packet) : new StringParserWithName(packet);
if (info.serverCapabilities & Capabilities.MARIADB_CLIENT_EXTENDED_TYPE_INFO) {

@@ -49,234 +50,2 @@ const subPacket = packet.subPacketLengthEncoded();

__parser(binary, opts) {
// set reader function read(packet, index, nullBitmap, opts)
// this permit for multi-row result-set to avoid resolving type parsing each data.
if (binary) {
switch (this.columnType) {
case FieldType.TINY:
if (this.signed()) {
return (packet, index, nullBitmap, opts) => (isNullBitmap(index, nullBitmap) ? null : packet.readInt8());
} else {
return (packet, index, nullBitmap, opts) => (isNullBitmap(index, nullBitmap) ? null : packet.readUInt8());
}
case FieldType.YEAR:
case FieldType.SHORT:
if (this.signed()) {
return (packet, index, nullBitmap, opts) => (isNullBitmap(index, nullBitmap) ? null : packet.readInt16());
} else {
return (packet, index, nullBitmap, opts) => (isNullBitmap(index, nullBitmap) ? null : packet.readUInt16());
}
case FieldType.INT24:
if (this.signed()) {
return (packet, index, nullBitmap, opts) => {
if (isNullBitmap(index, nullBitmap)) {
return null;
}
const result = packet.readInt24();
packet.skip(1); // MEDIUMINT is encoded on 4 bytes in exchanges !
return result;
};
} else {
return (packet, index, nullBitmap, opts) => {
if (isNullBitmap(index, nullBitmap)) {
return null;
}
const result = packet.readUInt24();
packet.skip(1); // MEDIUMINT is encoded on 4 bytes in exchanges !
return result;
};
}
case FieldType.INT:
if (this.signed()) {
return (packet, index, nullBitmap, opts) => (isNullBitmap(index, nullBitmap) ? null : packet.readInt32());
} else {
return (packet, index, nullBitmap, opts) => (isNullBitmap(index, nullBitmap) ? null : packet.readUInt32());
}
case FieldType.FLOAT:
return (packet, index, nullBitmap, opts) => (isNullBitmap(index, nullBitmap) ? null : packet.readFloat());
case FieldType.DOUBLE:
return (packet, index, nullBitmap, opts) => (isNullBitmap(index, nullBitmap) ? null : packet.readDouble());
case FieldType.BIGINT:
return (packet, index, nullBitmap, opts) => {
if (isNullBitmap(index, nullBitmap)) return null;
const val = this.signed() ? packet.readBigInt64() : packet.readBigUInt64();
if (val != null && (opts.bigIntAsNumber || opts.supportBigNumbers)) {
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(val)))) {
return val.toString();
}
return Number(val);
}
return val;
};
case FieldType.DATE:
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDate(opts);
case FieldType.DATETIME:
case FieldType.TIMESTAMP:
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDateTime(opts, this);
case FieldType.TIME:
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryTime();
case FieldType.DECIMAL:
case FieldType.NEWDECIMAL:
return (packet, index, nullBitmap, opts) => {
if (isNullBitmap(index, nullBitmap)) return null;
const valDec = packet.readDecimalLengthEncoded();
if (valDec != null && (opts.decimalAsNumber || opts.supportBigNumbers)) {
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(valDec)))) {
return valDec.toString();
}
return Number(valDec);
}
return valDec;
};
case FieldType.GEOMETRY:
let defaultVal = this.__getDefaultGeomVal();
return (packet, index, nullBitmap, opts) => {
if (isNullBitmap(index, nullBitmap)) {
return defaultVal;
}
return packet.readGeometry(defaultVal);
};
case FieldType.JSON:
//for mysql only => parse string as JSON object
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : JSON.parse(packet.readStringLengthEncoded());
case FieldType.BIT:
if (this.columnLength === 1 && opts.bitOneIsBoolean) {
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBufferLengthEncoded()[0] === 1;
}
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBufferLengthEncoded();
default:
if (this.dataTypeFormat && this.dataTypeFormat === 'json' && opts.autoJsonMap) {
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : JSON.parse(packet.readStringLengthEncoded());
}
if (this.collation.index === 63) {
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBufferLengthEncoded();
}
if (this.isSet()) {
return (packet, index, nullBitmap, opts) => {
if (isNullBitmap(index, nullBitmap)) return null;
const string = packet.readStringLengthEncoded();
return string == null ? null : string === '' ? [] : string.split(',');
};
}
return (packet, index, nullBitmap, opts) =>
isNullBitmap(index, nullBitmap) ? null : packet.readStringLengthEncoded();
}
} else {
switch (this.columnType) {
case FieldType.TINY:
case FieldType.SHORT:
case FieldType.INT:
case FieldType.INT24:
case FieldType.YEAR:
return (packet, index, nullBitmap, opts) => packet.readIntLengthEncoded();
case FieldType.FLOAT:
case FieldType.DOUBLE:
return (packet, index, nullBitmap, opts) => packet.readFloatLengthCoded();
case FieldType.BIGINT:
return (packet, index, nullBitmap, opts) => {
const val = packet.readBigIntLengthEncoded();
if (val != null && (opts.bigIntAsNumber || opts.supportBigNumbers)) {
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(val)))) {
return val.toString();
}
return Number(val);
}
return val;
};
case FieldType.DECIMAL:
case FieldType.NEWDECIMAL:
return (packet, index, nullBitmap, opts) => {
const valDec = packet.readDecimalLengthEncoded();
if (valDec != null && (opts.decimalAsNumber || opts.supportBigNumbers)) {
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(valDec)))) {
return valDec.toString();
}
return Number(valDec);
}
return valDec;
};
case FieldType.DATE:
return (packet, index, nullBitmap, opts) => {
if (opts.dateStrings) {
return packet.readAsciiStringLengthEncoded();
}
return packet.readDate();
};
case FieldType.DATETIME:
case FieldType.TIMESTAMP:
return (packet, index, nullBitmap, opts) => {
if (opts.dateStrings) {
return packet.readAsciiStringLengthEncoded();
}
return packet.readDateTime(opts);
};
case FieldType.TIME:
return (packet, index, nullBitmap, opts) => packet.readAsciiStringLengthEncoded();
case FieldType.GEOMETRY:
let defaultVal = this.__getDefaultGeomVal();
return (packet, index, nullBitmap, opts) => packet.readGeometry(defaultVal);
case FieldType.JSON:
//for mysql only => parse string as JSON object
return (packet, index, nullBitmap, opts) => JSON.parse(packet.readStringLengthEncoded());
case FieldType.BIT:
if (this.columnLength === 1 && opts.bitOneIsBoolean) {
return (packet, index, nullBitmap, opts) => {
const val = packet.readBufferLengthEncoded();
return val == null ? null : val[0] === 1;
};
}
return (packet, index, nullBitmap, opts) => packet.readBufferLengthEncoded();
default:
if (this.dataTypeFormat && this.dataTypeFormat === 'json' && opts.autoJsonMap) {
return (packet, index, nullBitmap, opts) => JSON.parse(packet.readStringLengthEncoded());
}
if (this.collation.index === 63) {
return (packet, index, nullBitmap, opts) => packet.readBufferLengthEncoded();
}
if (this.isSet()) {
return (packet, index, nullBitmap, opts) => {
const string = packet.readStringLengthEncoded();
return string == null ? null : string === '' ? [] : string.split(',');
};
}
return (packet, index, nullBitmap, opts) => packet.readStringLengthEncoded();
}
}
}
__getDefaultGeomVal() {

@@ -303,24 +72,25 @@ if (this.dataTypeName) {

}
db() {
return this._stringParser.packet.readString(this._stringParser.dbOffset, this._stringParser.dbLength);
return this.#stringParser.packet.readString(this.#stringParser.dbOffset, this.#stringParser.dbLength);
}
schema() {
return this._stringParser.packet.readString(this._stringParser.dbOffset, this._stringParser.dbLength);
return this.#stringParser.packet.readString(this.#stringParser.dbOffset, this.#stringParser.dbLength);
}
table() {
return this._stringParser.packet.readString(this._stringParser.tableOffset, this._stringParser.tableLength);
return this.#stringParser.packet.readString(this.#stringParser.tableOffset, this.#stringParser.tableLength);
}
orgTable() {
return this._stringParser.packet.readString(this._stringParser.orgTableOffset, this._stringParser.orgTableLength);
return this.#stringParser.packet.readString(this.#stringParser.orgTableOffset, this.#stringParser.orgTableLength);
}
name() {
return this._stringParser.packet.readString(this._stringParser.nameOffset, this._stringParser.nameLength);
return this.#stringParser.name();
}
orgName() {
return this._stringParser.packet.readString(this._stringParser.orgNameOffset, this._stringParser.orgNameLength);
return this.#stringParser.packet.readString(this.#stringParser.orgNameOffset, this.#stringParser.orgNameLength);
}

@@ -337,6 +107,2 @@

const isNullBitmap = (index, nullBitmap) => {
return (nullBitmap[Math.floor((index + 2) / 8)] & (1 << (index + 2) % 8)) > 0;
};
/**

@@ -371,4 +137,39 @@ * String parser.

}
name = function () {
return this.packet.readString(this.nameOffset, this.nameLength);
};
}
/**
* String parser.
* This object permits to avoid listing all private information to metadata object.
*/
class StringParserWithName {
constructor(packet) {
packet.skip(4); // skip 'def'
this.dbLength = packet.readUnsignedLength();
this.dbOffset = packet.pos;
packet.skip(this.dbLength);
this.tableLength = packet.readUnsignedLength();
this.tableOffset = packet.pos;
packet.skip(this.tableLength);
this.orgTableLength = packet.readUnsignedLength();
this.orgTableOffset = packet.pos;
packet.skip(this.orgTableLength);
this.colName = packet.readStringLengthEncoded();
this.orgNameLength = packet.readUnsignedLength();
this.orgNameOffset = packet.pos;
packet.skip(this.orgNameLength);
this.packet = packet;
}
name = function () {
return this.colName;
};
}
module.exports = ColumnDef;

@@ -14,4 +14,5 @@ 'use strict';

class Command extends EventEmitter {
constructor(resolve, reject) {
constructor(cmdParam, resolve, reject) {
super();
this.cmdParam = cmdParam;
this.sequenceNo = -1;

@@ -22,2 +23,3 @@ this.compressSequenceNo = -1;

this.sending = false;
this.unexpectedError = this.throwUnexpectedError.bind(this);
}

@@ -30,3 +32,3 @@

/**
* Throw an an unexpected error.
* Throw an unexpected error.
* server exchange will still be read to keep connection in a good state, but promise will be rejected.

@@ -41,3 +43,12 @@ *

throwUnexpectedError(msg, fatal, info, sqlState, errno) {
const err = Errors.createError(msg, errno, info, sqlState, this.displaySql(), fatal, this.stack, false);
const err = Errors.createError(
msg,
errno,
info,
sqlState,
this.displaySql(),
fatal,
this.cmdParam ? this.cmdParam.stack : null,
false
);
if (this.reject) {

@@ -78,3 +89,3 @@ process.nextTick(this.reject, err);

if (this.reject) {
if (this.stack) {
if (this.cmdParam && this.cmdParam.stack) {
err = Errors.createError(

@@ -87,3 +98,3 @@ err.text ? err.text : err.message,

err.fatal,
this.stack,
this.cmdParam.stack,
false

@@ -115,3 +126,3 @@ );

parseOkPacket(packet, out, opts, info) {
parseOkPacket(packet, out, opts, connectionOpts, info) {
packet.skip(1); //skip header

@@ -121,3 +132,7 @@

let insertId = packet.readSignedLengthBigInt();
info.status = packet.readUInt16();
if (insertId != null && (opts.supportBigNumbers || opts.insertIdAsNumber)) {
if (opts.insertIdAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(insertId))) {
throw new Error(`last insert id value ${insertId} can't safely be converted to number`);
}
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(insertId)))) {

@@ -127,3 +142,2 @@ insertId = insertId.toString();

}
info.status = packet.readUInt16();

@@ -151,3 +165,3 @@ const okPacket = new OkPacket(affectedRows, insertId, packet.readUInt16());

}
opts.emit('collation', info.collation);
connectionOpts.emit('collation', info.collation);
break;

@@ -154,0 +168,0 @@

'use strict';
const FieldType = require('../../const/field-type');
const Errors = require('../../misc/errors');
class BinaryDecoder {

@@ -54,5 +57,71 @@ static newRow(packet, columns) {

}
return column.readGeometry(defaultVal);
return packet.readGeometry(defaultVal);
};
}
static parser(col, opts) {
// set reader function read(col, packet, index, nullBitmap, opts, throwUnexpectedError)
// this permit for multi-row result-set to avoid resolving type parsing each data.
switch (col.columnType) {
case FieldType.TINY:
return col.signed() ? readTinyBinarySigned : readTinyBinaryUnsigned;
case FieldType.YEAR:
case FieldType.SHORT:
return col.signed() ? readShortBinarySigned : readShortBinaryUnsigned;
case FieldType.INT24:
return col.signed() ? readMediumBinarySigned : readMediumBinaryUnsigned;
case FieldType.INT:
return col.signed() ? readIntBinarySigned : readIntBinaryUnsigned;
case FieldType.FLOAT:
return readFloatBinary;
case FieldType.DOUBLE:
return readDoubleBinary;
case FieldType.BIGINT:
return opts.bigIntAsNumber || opts.supportBigNumbers ? readBigintAsIntBinary : readBigintBinary;
case FieldType.DATE:
return readDateBinary;
case FieldType.DATETIME:
case FieldType.TIMESTAMP:
return opts.dateStrings ? readTimestampStringBinary : readTimestampBinary;
case FieldType.TIME:
return readTimeBinary;
case FieldType.DECIMAL:
case FieldType.NEWDECIMAL:
return col.scale == 0 ? readDecimalAsIntBinary : readDecimalBinary;
case FieldType.GEOMETRY:
return readGeometryBinary;
case FieldType.JSON:
//for mysql only => parse string as JSON object
return readJsonBinary;
case FieldType.BIT:
if (col.columnLength === 1 && opts.bitOneIsBoolean) {
return readBitBinaryBoolean;
}
return readBinaryBuffer;
default:
if (col.dataTypeFormat && col.dataTypeFormat === 'json' && opts.autoJsonMap) {
return readJsonBinary;
}
if (col.collation.index === 63) {
return readBinaryBuffer;
}
if (col.isSet()) {
return readBinarySet;
}
return readStringBinary;
}
}
}

@@ -62,2 +131,119 @@ const isNullBitmap = (index, nullBitmap) => {

};
module.exports = BinaryDecoder;
const readTinyBinarySigned = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readInt8();
const readTinyBinaryUnsigned = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readUInt8();
const readShortBinarySigned = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readInt16();
const readShortBinaryUnsigned = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readUInt16();
const readMediumBinarySigned = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
if (isNullBitmap(index, nullBitmap)) {
return null;
}
const result = packet.readInt24();
packet.skip(1); // MEDIUMINT is encoded on 4 bytes in exchanges !
return result;
};
const readMediumBinaryUnsigned = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
if (isNullBitmap(index, nullBitmap)) {
return null;
}
const result = packet.readInt24();
packet.skip(1); // MEDIUMINT is encoded on 4 bytes in exchanges !
return result;
};
const readIntBinarySigned = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readInt32();
const readIntBinaryUnsigned = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readUInt32();
const readFloatBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readFloat();
const readDoubleBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readDouble();
const readBigintBinary = function (col, packet, index, nullBitmap, opts, throwUnexpectedError) {
if (isNullBitmap(index, nullBitmap)) return null;
return col.signed() ? packet.readBigInt64() : packet.readBigUInt64();
};
const readBigintAsIntBinary = function (col, packet, index, nullBitmap, opts, throwUnexpectedError) {
if (isNullBitmap(index, nullBitmap)) return null;
const val = col.signed() ? packet.readBigInt64() : packet.readBigUInt64();
if (opts.bigIntAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(val))) {
return throwUnexpectedError(
`value ${val} can't safely be converted to number`,
false,
null,
'42000',
Errors.ER_PARSING_PRECISION
);
}
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(val)))) {
return val.toString();
}
return Number(val);
};
const readGeometryBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
let defaultVal = col.__getDefaultGeomVal();
if (isNullBitmap(index, nullBitmap)) {
return defaultVal;
}
return packet.readGeometry(defaultVal);
};
const readDateBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDate(opts);
const readTimestampBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDateTime(opts);
const readTimestampStringBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDateTimeAsString(col.scale);
const readTimeBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryTime();
const readDecimalAsIntBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
//checkNumberRange additional check is only done when
// resulting value is an integer
if (isNullBitmap(index, nullBitmap)) return null;
const valDec = packet.readDecimalLengthEncoded();
if (valDec != null && (opts.decimalAsNumber || opts.supportBigNumbers)) {
if (opts.decimalAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(valDec))) {
return throwUnexpectedError(
`value ${valDec} can't safely be converted to number`,
false,
null,
'42000',
Errors.ER_PARSING_PRECISION
);
}
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(valDec)))) {
return valDec.toString();
}
return Number(valDec);
}
return valDec;
};
const readDecimalBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
if (isNullBitmap(index, nullBitmap)) return null;
const valDec = packet.readDecimalLengthEncoded();
if (valDec != null && (opts.decimalAsNumber || opts.supportBigNumbers)) {
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(valDec)))) {
return valDec.toString();
}
return Number(valDec);
}
return valDec;
};
const readJsonBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : JSON.parse(packet.readStringLengthEncoded());
const readBitBinaryBoolean = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBufferLengthEncoded()[0] === 1;
const readBinaryBuffer = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readBufferLengthEncoded();
const readBinarySet = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
if (isNullBitmap(index, nullBitmap)) return null;
const string = packet.readStringLengthEncoded();
return string == null ? null : string === '' ? [] : string.split(',');
};
const readStringBinary = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
isNullBitmap(index, nullBitmap) ? null : packet.readStringLengthEncoded();
'use strict';
const FieldType = require('../../const/field-type');
const Errors = require('../../misc/errors');
class TextDecoder {

@@ -44,10 +47,152 @@ static castWrapper(column, packet, index, nullBitmap, opts) {

if (isNullBitmap(index, nullBitmap)) {
return defaultVal;
}
return column.readGeometry(defaultVal);
return packet.readGeometry(defaultVal);
};
}
static parser(col, opts) {
// set reader function read(col, packet, index, nullBitmap, opts, throwUnexpectedError)
// this permit for multi-row result-set to avoid resolving type parsing each data.
switch (col.columnType) {
case FieldType.TINY:
case FieldType.SHORT:
case FieldType.INT:
case FieldType.INT24:
case FieldType.YEAR:
return readIntLengthEncoded;
case FieldType.FLOAT:
case FieldType.DOUBLE:
return readFloatLengthCoded;
case FieldType.BIGINT:
if (opts.bigIntAsNumber || opts.supportBigNumbers) return readBigIntAsNumberLengthCoded;
return readBigIntLengthCoded;
case FieldType.DECIMAL:
case FieldType.NEWDECIMAL:
return col.scale == 0 ? readDecimalAsIntLengthCoded : readDecimalLengthCoded;
case FieldType.DATE:
return readDate;
case FieldType.DATETIME:
case FieldType.TIMESTAMP:
return readTimestamp;
case FieldType.TIME:
return readAsciiStringLengthEncoded;
case FieldType.GEOMETRY:
return readGeometry;
case FieldType.JSON:
//for mysql only => parse string as JSON object
return readJson;
case FieldType.BIT:
if (col.columnLength === 1 && opts.bitOneIsBoolean) {
return readBitAsBoolean;
}
return readBufferLengthEncoded;
default:
if (col.dataTypeFormat && col.dataTypeFormat === 'json' && opts.autoJsonMap) {
return readJson;
}
if (col.collation.index === 63) {
return readBufferLengthEncoded;
}
if (col.isSet()) {
return readSet;
}
return readStringLengthEncoded;
}
}
}
module.exports = TextDecoder;
const readGeometry = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
let defaultVal = col.__getDefaultGeomVal();
return packet.readGeometry(defaultVal);
};
const readIntLengthEncoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
packet.readIntLengthEncoded();
const readStringLengthEncoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
packet.readStringLengthEncoded();
const readFloatLengthCoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
packet.readFloatLengthCoded();
const readBigIntLengthCoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
packet.readBigIntLengthEncoded();
const readBigIntAsNumberLengthCoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
const val = packet.readBigIntLengthEncoded();
if (val == null) return null;
if (opts.bigIntAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(val))) {
return throwUnexpectedError(
`value ${val} can't safely be converted to number`,
false,
null,
'42000',
Errors.ER_PARSING_PRECISION
);
}
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(val)))) {
return val.toString();
}
return Number(val);
};
const readDecimalAsIntLengthCoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
const valDec = packet.readDecimalLengthEncoded();
if (valDec != null && (opts.decimalAsNumber || opts.supportBigNumbers)) {
if (opts.decimalAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(valDec))) {
return throwUnexpectedError(
`value ${valDec} can't safely be converted to number`,
false,
null,
'42000',
Errors.ER_PARSING_PRECISION
);
}
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(valDec)))) {
return valDec.toString();
}
return Number(valDec);
}
return valDec;
};
const readDecimalLengthCoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
const valDec = packet.readDecimalLengthEncoded();
if (valDec != null && (opts.decimalAsNumber || opts.supportBigNumbers)) {
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(valDec)))) {
return valDec.toString();
}
return Number(valDec);
}
return valDec;
};
const readDate = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
if (opts.dateStrings) {
return packet.readAsciiStringLengthEncoded();
}
return packet.readDate();
};
const readTimestamp = (col, packet, index, nullBitmap, opts, throwUnexpectedError) => {
if (opts.dateStrings) {
return packet.readAsciiStringLengthEncoded();
}
return packet.readDateTime(opts);
};
const readAsciiStringLengthEncoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
packet.readAsciiStringLengthEncoded();
const readBitAsBoolean = (col, packet, index, nullBitmap, opts) => {
const val = packet.readBufferLengthEncoded();
return val == null ? null : val[0] === 1;
};
const readBufferLengthEncoded = (col, packet, index, nullBitmap, opts, throwUnexpectedError) =>
packet.readBufferLengthEncoded();
const readJson = (col, packet, index, nullBitmap, opts) => JSON.parse(packet.readStringLengthEncoded());
const readSet = (col, packet, index, nullBitmap, opts) => {
const string = packet.readStringLengthEncoded();
return string == null ? null : string === '' ? [] : string.split(',');
};

@@ -32,2 +32,3 @@ 'use strict';

writeParam(out, value, opts, info) {
// GEOJSON are not checked, because change to null/Buffer on parameter validation
switch (typeof value) {

@@ -65,23 +66,3 @@ case 'boolean':

} else {
if (
value.type != null &&
[
'Point',
'LineString',
'Polygon',
'MultiPoint',
'MultiLineString',
'MultiPolygon',
'GeometryCollection'
].includes(value.type)
) {
const geoBuff = BinaryEncoder.getBufferFromGeometryValue(value);
const completeBuf = Buffer.concat([
Buffer.from([0, 0, 0, 0]), // SRID
geoBuff // WKB
]);
out.writeLengthEncodedBuffer(completeBuf);
} else {
out.writeLengthEncodedString(JSON.stringify(value));
}
out.writeLengthEncodedString(JSON.stringify(value));
}

@@ -88,0 +69,0 @@ break;

@@ -14,4 +14,4 @@ 'use strict';

class Execute extends Parser {
constructor(resolve, reject, options, connOpts, prepare, values) {
super(resolve, reject, options, connOpts, prepare.query, values);
constructor(resolve, reject, connOpts, cmdParam, prepare) {
super(resolve, reject, connOpts, cmdParam);
this.encoder = new BinaryEncoder(this.opts);

@@ -223,3 +223,3 @@ this.binary = true;

if (Object.prototype.toString.call(val) === '[object Date]') {
out.writeInt8(FieldType.TIMESTAMP);
out.writeInt8(FieldType.DATETIME);
} else if (Buffer.isBuffer(val)) {

@@ -226,0 +226,0 @@ out.writeInt8(FieldType.BLOB);

@@ -19,4 +19,4 @@ const PluginAuth = require('./plugin-auth');

class CachingSha2PasswordAuth extends PluginAuth {
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
super(resolve, reject, multiAuthResolver);
constructor(packSeq, compressPackSeq, pluginData, cmdParam, resolve, reject, multiAuthResolver) {
super(cmdParam, resolve, reject, multiAuthResolver);
this.pluginData = pluginData;

@@ -23,0 +23,0 @@ this.sequenceNo = packSeq;

@@ -8,4 +8,4 @@ const PluginAuth = require('./plugin-auth');

class ClearPasswordAuth extends PluginAuth {
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
super(resolve, reject, multiAuthResolver);
constructor(packSeq, compressPackSeq, pluginData, cmdParam, resolve, reject, multiAuthResolver) {
super(cmdParam, resolve, reject, multiAuthResolver);
this.sequenceNo = packSeq;

@@ -16,3 +16,10 @@ }

out.startPacket(this);
if (opts.password) out.writeString(opts.password);
const pwd = opts.password;
if (pwd) {
if (Array.isArray(pwd)) {
out.writeString(pwd[0]);
} else {
out.writeString(pwd);
}
}
out.writeInt8(0);

@@ -19,0 +26,0 @@ out.flushPacket();

@@ -10,4 +10,4 @@ 'use strict';

class Ed25519PasswordAuth extends PluginAuth {
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
super(resolve, reject, multiAuthResolver);
constructor(packSeq, compressPackSeq, pluginData, cmdParam, resolve, reject, multiAuthResolver) {
super(cmdParam, resolve, reject, multiAuthResolver);
this.pluginData = pluginData;

@@ -14,0 +14,0 @@ this.sequenceNo = packSeq;

@@ -10,4 +10,4 @@ 'use strict';

class NativePasswordAuth extends PluginAuth {
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
super(resolve, reject, multiAuthResolver);
constructor(packSeq, compressPackSeq, pluginData, cmdParam, resolve, reject, multiAuthResolver) {
super(cmdParam, resolve, reject, multiAuthResolver);
this.pluginData = pluginData;

@@ -14,0 +14,0 @@ this.sequenceNo = packSeq;

@@ -7,4 +7,4 @@ const PluginAuth = require('./plugin-auth');

class PamPasswordAuth extends PluginAuth {
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
super(resolve, reject, multiAuthResolver);
constructor(packSeq, compressPackSeq, pluginData, cmdParam, resolve, reject, multiAuthResolver) {
super(cmdParam, resolve, reject, multiAuthResolver);
this.pluginData = pluginData;

@@ -11,0 +11,0 @@ this.sequenceNo = packSeq;

@@ -9,4 +9,4 @@ 'use strict';

class PluginAuth extends Command {
constructor(resolve, reject, multiAuthResolver) {
super(resolve, reject);
constructor(cmdParam, resolve, reject, multiAuthResolver) {
super(cmdParam, resolve, reject);
this.multiAuthResolver = multiAuthResolver;

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

@@ -10,4 +10,4 @@ const PluginAuth = require('./plugin-auth');

class Sha256PasswordAuth extends PluginAuth {
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
super(resolve, reject, multiAuthResolver);
constructor(packSeq, compressPackSeq, pluginData, cmdParam, resolve, reject, multiAuthResolver) {
super(cmdParam, resolve, reject, multiAuthResolver);
this.pluginData = pluginData;

@@ -14,0 +14,0 @@ this.sequenceNo = packSeq;

@@ -18,4 +18,5 @@ 'use strict';

class Handshake extends Command {
constructor(resolve, reject, _createSecureContext, _addCommand, getSocket) {
super(resolve, reject);
constructor(cmdParam, resolve, reject, _createSecureContext, _addCommand, getSocket) {
super(cmdParam, resolve, reject);
this.cmdParam = cmdParam;
this._createSecureContext = _createSecureContext;

@@ -28,24 +29,2 @@ this._addCommand = _addCommand;

ensureOptionCompatibility(opts, info) {
if (opts.multipleStatements && (info.serverCapabilities & Capabilities.MULTI_STATEMENTS) === 0) {
return this.throwNewError(
"Option `multipleStatements` enable, but server doesn'permits multi-statment",
true,
info,
'08S01',
Errors.ER_CLIENT_OPTION_INCOMPATIBILITY
);
}
if (opts.permitLocalInfile && (info.serverCapabilities & Capabilities.LOCAL_FILES) === 0) {
return this.throwNewError(
"Option `permitLocalInfile` enable, but server doesn'permits using local file",
true,
info,
'08S01',
Errors.ER_CLIENT_OPTION_INCOMPATIBILITY
);
}
}
parseHandshakeInit(packet, out, opts, info) {

@@ -60,3 +39,2 @@ if (packet.peek() === 0xff) {

let handshake = new InitialHandshake(packet, info);
this.ensureOptionCompatibility(opts, info);

@@ -70,7 +48,5 @@ // handle default collation.

}
} else {
} else if (info.collation.charset !== 'utf8' || info.collation.maxLength === 3) {
// if not utf8mb4 and no configuration, force to use UTF8MB4_UNICODE_CI
if (info.collation.charset !== 'utf8' || info.collation.maxLength === 3) {
info.collation = Collations.fromIndex(224);
}
info.collation = Collations.fromIndex(224);
}

@@ -186,5 +162,6 @@

} else {
pluginName = packet.readStringNullEnded('cesu8');
pluginName = packet.readStringNullEnded('ascii');
pluginData = packet.readBufferRemaining();
}
if (opts.restrictedAuth && !opts.restrictedAuth.includes(pluginName)) {

@@ -209,2 +186,3 @@ this.throwNewError(

out,
this.cmdParam,
this.resolve,

@@ -219,14 +197,3 @@ this.reject,

if (!this.plugin) {
this.reject(
Errors.createFatalError(
"Client does not support authentication protocol '" + pluginName + "' requested by server. ",
Errors.ER_AUTHENTICATION_PLUGIN_NOT_SUPPORTED,
info,
'08004'
)
);
} else {
this._addCommand(this.plugin);
}
this._addCommand(this.plugin);
}

@@ -242,2 +209,3 @@

out,
cmdParam,
authResolve,

@@ -266,10 +234,2 @@ authReject,

case 'sha256_password':
if (!Handshake.ensureNodeVersion(11, 6, 0)) {
throw Errors.createFatalError(
'sha256_password authentication plugin require node 11.6+',
Errors.ER_MINIMUM_NODE_VERSION_REQUIRED,
info,
'08004'
);
}
pluginAuth = require('./auth/sha256-password-auth.js');

@@ -279,10 +239,2 @@ break;

case 'caching_sha2_password':
if (!Handshake.ensureNodeVersion(11, 6, 0)) {
throw Errors.createFatalError(
'caching_sha2_password authentication plugin require node 11.6+',
Errors.ER_MINIMUM_NODE_VERSION_REQUIRED,
info,
'08004'
);
}
pluginAuth = require('./auth/caching-sha2-password-auth.js');

@@ -294,17 +246,13 @@ break;

default:
return null;
throw Errors.createFatalError(
`Client does not support authentication protocol '${pluginName}' requested by server.`,
Errors.ER_AUTHENTICATION_PLUGIN_NOT_SUPPORTED,
info,
'08004'
);
}
return new pluginAuth(packSeq, compressPackSeq, pluginData, authResolve, authReject, multiAuthResolver);
return new pluginAuth(packSeq, compressPackSeq, pluginData, cmdParam, authResolve, authReject, multiAuthResolver);
}
static ensureNodeVersion(major, minor, patch) {
const ver = process.versions.node.split('.');
return (
ver[0] > major ||
(ver[0] === major && ver[1] > minor) ||
(ver[0] === major && ver[1] === minor && ver[2] >= patch)
);
}
}
module.exports = Handshake;

@@ -17,9 +17,9 @@ 'use strict';

class Parser extends Command {
constructor(resolve, reject, cmdOpts, connOpts, sql, values) {
super(resolve, reject);
constructor(resolve, reject, connOpts, cmdParam) {
super(cmdParam, resolve, reject);
this._responseIndex = 0;
this._rows = [];
this.opts = cmdOpts ? Object.assign({}, connOpts, cmdOpts) : connOpts;
this.sql = sql;
this.initialValues = values;
this.opts = cmdParam.opts ? Object.assign({}, connOpts, cmdParam.opts) : connOpts;
this.sql = cmdParam.sql;
this.initialValues = cmdParam.values;
this.canSkipMeta = false;

@@ -109,10 +109,16 @@ }

readOKPacket(packet, out, opts, info) {
const okPacket = this.parseOkPacket(packet, out, this.opts, info);
this._rows.push(okPacket);
try {
const okPacket = this.parseOkPacket(packet, out, this.opts, opts, info);
this._rows.push(okPacket);
if (info.status & ServerStatus.MORE_RESULTS_EXISTS) {
this._responseIndex++;
return (this.onPacketReceive = this.readResponsePacket);
if (info.status & ServerStatus.MORE_RESULTS_EXISTS) {
this._responseIndex++;
return (this.onPacketReceive = this.readResponsePacket);
}
this.success(this._responseIndex === 0 ? this._rows[0] : this._rows);
} catch (e) {
this.onPacketReceive = info.status & ServerStatus.MORE_RESULTS_EXISTS ? this.readResponsePacket : null;
this.throwUnexpectedError(e.message, false, info, '42000', Errors.ER_PARSING_PRECISION);
return null;
}
this.success(this._responseIndex === 0 ? this._rows[0] : this._rows);
}

@@ -169,3 +175,3 @@

this.columnNo--;
this._columnsPrepare.push(new ColumnDefinition(packet.clone(), info));
this._columnsPrepare.push(new ColumnDefinition(packet, info, opts.rowsAsArray));
if (this.columnNo === 0) {

@@ -186,3 +192,3 @@ if (info.eofDeprecated) {

this.parameterNo--;
this._parameterPrepare.push(new ColumnDefinition(packet.clone(), info));
this._parameterPrepare.push(new ColumnDefinition(packet, info));
if (this.parameterNo === 0) {

@@ -214,3 +220,3 @@ if (info.eofDeprecated) {

readColumn(packet, out, opts, info) {
this._columns.push(new ColumnDefinition(packet.clone(), info));
this._columns.push(new ColumnDefinition(packet, info, this.opts.rowsAsArray));

@@ -235,7 +241,8 @@ // last column

for (let i = 0; i < this._columnCount; i++) {
this._parseFonction[i] = this.readCastValue.bind(this, this._columns[i]);
this._parseFonction[i] = this.readCastValue.bind(this);
}
} else {
const dataParser = this.binary ? BinaryDecoder.parser : TextDecoder.parser;
for (let i = 0; i < this._columnCount; i++) {
this._parseFonction[i] = this._columns[i].__parser(this.binary, this.opts);
this._parseFonction[i] = dataParser(this._columns[i], this.opts);
}

@@ -471,3 +478,3 @@ }

for (let i = 0; i < this._columnCount; i++) {
row[i] = this._parseFonction[i].call(null, packet, i, nullBitMap, this.opts);
row[i] = this._parseFonction[i].call(null, columns[i], packet, i, nullBitMap, this.opts, this.unexpectedError);
}

@@ -484,6 +491,8 @@ return row;

null,
columns[i],
packet,
i,
nullBitMap,
this.opts
this.opts,
this.unexpectedError
);

@@ -497,3 +506,3 @@ }

for (let i = 0; i < this._columnCount; i++) {
row[this.tableHeader[i]] = this._parseFonction[i].call(null, packet, i, null, this.opts);
row[this.tableHeader[i]] = this._parseFonction[i](columns[i], packet, i, null, this.opts, this.unexpectedError);
}

@@ -507,3 +516,11 @@ return row;

for (let i = 0; i < this._columnCount; i++) {
row[this.tableHeader[i]] = this._parseFonction[i].call(null, packet, i, nullBitMap, this.opts);
row[this.tableHeader[i]] = this._parseFonction[i].call(
null,
columns[i],
packet,
i,
nullBitMap,
this.opts,
this.unexpectedError
);
}

@@ -519,3 +536,7 @@ return row;

}
return opts.typeCast(column, column.__parser(this.binary, opts).bind(column, packet, index, nullBitmap, opts));
const dataParser = this.binary ? BinaryDecoder.parser : TextDecoder.parser;
return opts.typeCast(
column,
dataParser(column, opts).bind(null, column, packet, index, nullBitmap, opts, this.unexpectedError)
);
}

@@ -522,0 +543,0 @@

@@ -11,4 +11,4 @@ 'use strict';

class Ping extends Command {
constructor(resolve, reject) {
super(resolve, reject);
constructor(cmdParam, resolve, reject) {
super(cmdParam, resolve, reject);
}

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

readPingResponsePacket(packet, out, opts, info) {
if (packet.peek() !== 0x00) {
return this.throwNewError('unexpected packet', false, info, '42000', Errors.ER_PING_BAD_PACKET);
}
packet.skip(1); //skip header

@@ -42,0 +39,0 @@ packet.skipLengthCodedNumber(); //affected rows

@@ -13,4 +13,4 @@ 'use strict';

class Prepare extends Parser {
constructor(resolve, reject, opts, connOpts, sql, executePromise, emitter) {
super(resolve, reject, opts, connOpts, sql, null);
constructor(resolve, reject, connOpts, cmdParam, executePromise, emitter) {
super(resolve, reject, connOpts, cmdParam);
this.encoder = new BinaryEncoder(this.opts);

@@ -68,3 +68,4 @@ this.binary = true;

this.executePromise,
this.emitter
this.emitter,
opts
);

@@ -81,3 +82,4 @@ info._prepareCache.set(key, prepare);

this.executePromise,
this.emitter
this.emitter,
opts
);

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

@@ -15,4 +15,4 @@ 'use strict';

class Query extends Parser {
constructor(resolve, reject, options, connOpts, sql, values) {
super(resolve, reject, options, connOpts, sql, values);
constructor(resolve, reject, connOpts, cmdParam) {
super(resolve, reject, connOpts, cmdParam);
this.encoder = new TextEncoder(this.opts);

@@ -19,0 +19,0 @@ this.binary = false;

@@ -10,4 +10,4 @@ 'use strict';

class Quit extends Command {
constructor(resolve, reject) {
super(resolve, reject);
constructor(cmdParam, resolve, reject) {
super(cmdParam, resolve, reject);
}

@@ -14,0 +14,0 @@

@@ -11,4 +11,4 @@ 'use strict';

class Reset extends Command {
constructor(resolve, reject) {
super(resolve, reject);
constructor(cmdParam, resolve, reject) {
super(cmdParam, resolve, reject);
}

@@ -15,0 +15,0 @@

@@ -11,10 +11,8 @@ 'use strict';

class Stream extends Query {
constructor(cmdOpts, connOpts, sql, values, socket) {
constructor(cmdParam, connOpts, socket) {
super(
() => {},
() => {},
cmdOpts,
connOpts,
sql,
values
cmdParam
);

@@ -54,8 +52,4 @@ this.socket = socket;

handleNewRows(row) {
try {
if (!this.inStream.push(row)) {
this.socket.pause();
}
} catch (err) {
this.socket.resume();
if (!this.inStream.push(row)) {
this.socket.pause();
}

@@ -62,0 +56,0 @@ }

@@ -51,3 +51,3 @@ 'use strict';

} else {
this.collation = Collations.fromIndex(opts.charsetNumber);
this.collation = opts.charsetNumber ? Collations.fromIndex(opts.charsetNumber) : undefined;
}

@@ -132,2 +132,3 @@

this.bulk = opts.bulk === undefined || opts.bulk;
this.checkNumberRange = opts.checkNumberRange || false;

@@ -134,0 +135,0 @@ // coherence check

@@ -6,2 +6,3 @@ 'use strict';

const Query = require('./cmd/query');
const CommandParameter = require('./command-parameter');

@@ -25,8 +26,15 @@ class ConnectionCallback {

get status() {
return this.#conn.status;
}
#noop = () => {};
release = (cb) => {
this.#conn.release(
() => {
if (cb) cb();
},
(err) => {
if (cb) cb(err);
}
);
};
/**

@@ -49,8 +57,10 @@ * Permit to change user during connection.

}
const cmdParam = new CommandParameter(null, null, _options, _cb);
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
new Promise(this.#conn.changeUser.bind(this.#conn, _options))
new Promise(this.#conn.changeUser.bind(this.#conn, cmdParam))
.then(() => {
if (_cb) _cb(null, null, null);
if (cmdParam.callback) cmdParam.callback(null, null, null);
})
.catch(_cb || this.#noop);
.catch(cmdParam.callback || this.#noop);
}

@@ -64,3 +74,3 @@

beginTransaction(callback) {
this.query('START TRANSACTION', null, callback);
this.query(new CommandParameter('START TRANSACTION'), null, callback);
}

@@ -75,3 +85,3 @@

this.#conn.changeTransaction(
'COMMIT',
new CommandParameter('COMMIT'),
() => {

@@ -91,3 +101,3 @@ if (callback) callback(null, null, null);

this.#conn.changeTransaction(
'ROLLBACK',
new CommandParameter('ROLLBACK'),
() => {

@@ -111,37 +121,18 @@ if (callback) callback(null, null, null);

query(sql, values, callback) {
return ConnectionCallback._QUERY_CMD(this.#conn, sql, values, callback);
const cmdParam = ConnectionCallback._PARAM(this.#conn.opts, sql, values, callback);
return ConnectionCallback._QUERY_CMD(this.#conn, cmdParam);
}
static _QUERY_CMD(conn, sql, values, callback) {
let _cmdOpts,
_sql,
_values = values,
_cb = callback;
if (typeof values === 'function') {
_cb = values;
_values = undefined;
}
if (typeof sql === 'object') {
_cmdOpts = sql;
_sql = _cmdOpts.sql;
if (sql.values) _values = sql.values;
} else {
_sql = sql;
}
static _QUERY_CMD(conn, cmdParam) {
const cmd = new Query(
_cb
cmdParam.callback
? (rows) => {
const meta = rows.meta;
delete rows.meta;
_cb(null, rows, meta);
cmdParam.callback(null, rows, meta);
}
: () => {},
_cb ? _cb : () => {},
_cmdOpts,
cmdParam.callback ? cmdParam.callback : () => {},
conn.opts,
_sql,
_values
cmdParam
);

@@ -154,3 +145,2 @@

if (conn.opts.trace) Error.captureStackTrace(cmd);
conn.addCommand(cmd);

@@ -161,6 +151,7 @@ return cmd;

execute(sql, values, callback) {
return ConnectionCallback._EXECUTE_CMD(this.#conn, sql, values, callback);
const cmdParam = ConnectionCallback._PARAM(this.#conn.opts, sql, values, callback);
return ConnectionCallback._EXECUTE_CMD(this.#conn, cmdParam);
}
static _EXECUTE_CMD(conn, sql, values, callback) {
static _PARAM(options, sql, values, callback) {
let _cmdOpt,

@@ -170,2 +161,6 @@ _sql,

_cb = callback;
if (typeof values === 'function') {
_cb = values;
_values = undefined;
}
if (typeof sql === 'object') {

@@ -178,15 +173,16 @@ _cmdOpt = sql;

}
if (typeof values === 'function') {
_cb = values;
_values = undefined;
}
const cmdParam = new CommandParameter(_sql, _values, _cmdOpt, _cb);
if (options.trace) Error.captureStackTrace(cmdParam);
return cmdParam;
}
new Promise(conn.prepare.bind(conn, _cmdOpt, _sql, conn.executePromise.bind(conn)))
static _EXECUTE_CMD(conn, cmdParam) {
new Promise(conn.prepare.bind(conn, cmdParam, conn.executePromise.bind(conn)))
.then((prepare) => {
return prepare.execute(_values, _cmdOpt).then((res) => {
return prepare.execute(cmdParam.values, cmdParam.opts, null, cmdParam.stack).then((res) => {
prepare.close();
if (_cb) {
if (cmdParam.callback) {
const meta = res.meta;
delete res.meta;
_cb(null, res, meta);
cmdParam.callback(null, res, meta);
}

@@ -197,3 +193,3 @@ });

if (conn.opts.logger.error) conn.opts.logger.error(err);
if (_cb) _cb(err);
if (cmdParam.callback) cmdParam.callback(err);
});

@@ -210,3 +206,5 @@ }

}
return new Promise(this.#conn.prepare.bind(this.#conn, _cmdOpt, _sql, this.#conn.executePromise.bind(this.#conn)))
const cmdParam = new CommandParameter(_sql, null, _cmdOpt, callback);
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
return new Promise(this.#conn.prepare.bind(this.#conn, cmdParam, this.#conn.executePromise.bind(this.#conn)))
.then((prepare) => {

@@ -228,30 +226,15 @@ if (callback) callback(null, prepare, null);

batch(sql, values, callback) {
return ConnectionCallback._BATCH_CMD(this.#conn, sql, values, callback);
const cmdParam = ConnectionCallback._PARAM(this.#conn.opts, sql, values, callback);
return ConnectionCallback._BATCH_CMD(this.#conn, cmdParam);
}
static _BATCH_CMD(conn, sql, values, callback) {
let _options,
_sql,
_values = values,
_cb = callback;
if (typeof values === 'function') {
_cb = values;
_values = undefined;
}
if (typeof sql === 'object') {
_options = sql;
_sql = _options.sql;
if (_options.values) _values = _options.values;
} else {
_sql = sql;
}
static _BATCH_CMD(conn, cmdParam) {
conn
.batch(_sql, _options, _values)
.batch(cmdParam)
.then((res) => {
if (_cb) _cb(null, res);
if (cmdParam.callback) cmdParam.callback(null, res);
})
.catch((err) => {
if (conn.opts.logger.error) conn.opts.logger.error(err);
if (_cb) _cb(err);
if (cmdParam.callback) cmdParam.callback(err);
});

@@ -266,11 +249,13 @@ }

ping(timeout, callback) {
let _timeout, _cb;
let _cmdOpt = {},
_cb;
if (typeof timeout === 'function') {
_cb = timeout;
_timeout = undefined;
} else {
_timeout = timeout;
_cmdOpt.timeout = timeout;
_cb = callback;
}
new Promise(this.#conn.ping.bind(this.#conn, _timeout)).then(_cb || this.#noop).catch(_cb || this.#noop);
const cmdParam = new CommandParameter(null, null, _cmdOpt, _cb);
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
new Promise(this.#conn.ping.bind(this.#conn, cmdParam)).then(_cb || this.#noop).catch(_cb || this.#noop);
}

@@ -290,3 +275,7 @@

reset(callback) {
return new Promise(this.#conn.reset.bind(this.#conn)).then(callback || this.#noop).catch(callback || this.#noop);
const cmdParam = new CommandParameter();
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
return new Promise(this.#conn.reset.bind(this.#conn, cmdParam))
.then(callback || this.#noop)
.catch(callback || this.#noop);
}

@@ -308,3 +297,5 @@

end(callback) {
new Promise(this.#conn.end.bind(this.#conn))
const cmdParam = new CommandParameter();
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
new Promise(this.#conn.end.bind(this.#conn, cmdParam))
.then(() => {

@@ -311,0 +302,0 @@ if (callback) callback();

'use strict';
const Stream = require('./cmd/stream');
const CommandParameter = require('./command-parameter');

@@ -21,3 +22,2 @@ /**

this.#conn = conn;
this.query = ConnectionPromise._QUERY_CMD.bind(this, conn);
this.on = this.#conn.on.bind(this.#conn);

@@ -35,6 +35,2 @@ this.once = this.#conn.once.bind(this.#conn);

get status() {
return this.#conn.status;
}
/**

@@ -49,3 +45,5 @@ * Permit to change user during connection.

changeUser(options) {
return new Promise(this.#conn.changeUser.bind(this.#conn, options));
const cmdParam = new CommandParameter(null, null, options);
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
return new Promise(this.#conn.changeUser.bind(this.#conn, cmdParam));
}

@@ -68,3 +66,4 @@

commit() {
return new Promise(this.#conn.changeTransaction.bind(this.#conn, 'COMMIT'));
const cmdParam = ConnectionPromise._PARAM(this.#conn.opts, 'COMMIT');
return new Promise(this.#conn.changeTransaction.bind(this.#conn, cmdParam));
}

@@ -78,3 +77,4 @@

rollback() {
return new Promise(this.#conn.changeTransaction.bind(this.#conn, 'ROLLBACK'));
const cmdParam = ConnectionPromise._PARAM(this.#conn.opts, 'ROLLBACK');
return new Promise(this.#conn.changeTransaction.bind(this.#conn, cmdParam));
}

@@ -90,4 +90,12 @@

*/
query(sql, values) {
const cmdParam = ConnectionPromise._PARAM(this.#conn.opts, sql, values);
return new Promise(this.#conn.query.bind(this.#conn, cmdParam));
}
static _QUERY_CMD(conn, sql, values) {
static _QUERY_CMD(conn, cmdParam) {
return new Promise(conn.query.bind(conn, cmdParam));
}
static _PARAM(options, sql, values) {
let _cmdOpt,

@@ -101,25 +109,16 @@ _sql = sql,

}
return new Promise(conn.query.bind(conn, _cmdOpt, _sql, _values));
const cmdParam = new CommandParameter(_sql, _values, _cmdOpt);
if (options.trace) Error.captureStackTrace(cmdParam);
return cmdParam;
}
execute(sql, values) {
return ConnectionPromise._EXECUTE_CMD(this.#conn, sql, values);
const cmdParam = ConnectionPromise._PARAM(this.#conn.opts, sql, values);
return ConnectionPromise._EXECUTE_CMD(this.#conn, cmdParam);
}
static _EXECUTE_CMD(conn, sql, values) {
let _cmdOpt,
_sql,
_values = values;
if (typeof sql === 'object') {
_cmdOpt = sql;
_sql = _cmdOpt.sql;
if (_cmdOpt.values) _values = _cmdOpt.values;
} else {
_sql = sql;
}
return new Promise(conn.prepare.bind(conn, _cmdOpt, _sql, conn.executePromise.bind(conn)))
static _EXECUTE_CMD(conn, cmdParam) {
return new Promise(conn.prepare.bind(conn, cmdParam, conn.executePromise.bind(conn)))
.then((prepare) => {
return prepare.execute(_values, _cmdOpt).then((res) => {
return prepare.execute(cmdParam.values, cmdParam.opts, null, cmdParam.stack).then((res) => {
prepare.close();

@@ -143,3 +142,5 @@ return Promise.resolve(res);

}
return new Promise(this.#conn.prepare.bind(this.#conn, _cmdOpt, _sql, this.#conn.executePromise.bind(this.#conn)));
const cmdParam = new CommandParameter(_sql, null, _cmdOpt);
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
return new Promise(this.#conn.prepare.bind(this.#conn, cmdParam, this.#conn.executePromise.bind(this.#conn)));
}

@@ -156,18 +157,8 @@

batch(sql, values) {
return ConnectionPromise._BATCH_CMD(this.#conn, sql, values);
const cmdParam = ConnectionPromise._PARAM(this.#conn.opts, sql, values);
return this.#conn.batch(cmdParam);
}
static _BATCH_CMD(conn, sql, values) {
let _options,
_sql,
_values = values;
if (typeof sql === 'object') {
_options = sql;
_sql = _options.sql;
if (_options.values) _values = _options.values;
} else {
_sql = sql;
}
return conn.batch(_sql, _options, _values);
static _BATCH_CMD(conn, cmdParam) {
return conn.batch(cmdParam);
}

@@ -185,16 +176,5 @@

queryStream(sql, values) {
let _cmdOpt,
_sql,
_values = values;
if (typeof sql === 'object') {
_cmdOpt = sql;
_sql = _cmdOpt.sql;
if (sql.values) _values = sql.values;
} else {
_sql = sql;
}
const cmd = new Stream(_cmdOpt, this.#conn.opts, _sql, _values, this.#conn.socket);
const cmdParam = ConnectionPromise._PARAM(this.#conn.opts, sql, values);
const cmd = new Stream(cmdParam, this.#conn.opts, this.#conn.socket);
if (this.#conn.opts.logger.error) cmd.on('error', this.#conn.opts.logger.error);
if (this.#conn.opts.trace) Error.captureStackTrace(cmd);
this.#conn.addCommand(cmd);

@@ -210,3 +190,5 @@ return cmd.inStream;

ping(timeout) {
return new Promise(this.#conn.ping.bind(this.#conn, timeout));
const cmdParam = new CommandParameter(null, null, { timeout: timeout });
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
return new Promise(this.#conn.ping.bind(this.#conn, cmdParam));
}

@@ -226,3 +208,5 @@

reset() {
return new Promise(this.#conn.reset.bind(this.#conn));
const cmdParam = new CommandParameter();
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
return new Promise(this.#conn.reset.bind(this.#conn, cmdParam));
}

@@ -244,3 +228,5 @@

end() {
return new Promise(this.#conn.end.bind(this.#conn));
const cmdParam = new CommandParameter();
if (this.#conn.opts.trace) Error.captureStackTrace(cmdParam);
return new Promise(this.#conn.end.bind(this.#conn, cmdParam));
}

@@ -247,0 +233,0 @@

@@ -32,2 +32,3 @@ 'use strict';

const { Status } = require('./const/connection_status');
const CommandParameter = require('./command-parameter');

@@ -51,3 +52,2 @@ /**

status = Status.NOT_CONNECTED;
socketConnected = false;
socket = null;

@@ -83,2 +83,3 @@ timeout = null;

new ClosePrepare(
new CommandParameter(null, null, null, null),
() => {},

@@ -106,30 +107,34 @@ () => {},

const conn = this;
switch (this.status) {
case Status.NOT_CONNECTED:
this.status = Status.CONNECTING;
return new Promise(function (resolve, reject) {
conn.registerHandshakeCmd(resolve, reject);
});
this.status = Status.CONNECTING;
const handshakeParam = new CommandParameter(null, null, this.opts, null);
return new Promise(function (resolve, reject) {
conn.connectRejectFct = reject;
conn.connectResolveFct = resolve;
// add a handshake to msg queue
const handshake = new Handshake(
handshakeParam,
conn.authSucceedHandler.bind(conn),
conn.authFailHandler.bind(conn),
conn.createSecureContext.bind(conn),
conn.addCommandEnable.bind(conn),
conn.getSocket.bind(conn)
);
Error.captureStackTrace(handshake);
case Status.CLOSING:
case Status.CLOSED:
const err = Errors.createFatalError('Connection closed', Errors.ER_CONNECTION_ALREADY_CLOSED, this.info);
if (this.opts.logger.error) this.opts.logger.error(err);
return Promise.reject(err);
handshake.once('end', () => {
// conn.info.collation might not be initialized
// in case of handshake throwing error
if (!conn.opts.collation && conn.info.collation) {
conn.opts.emit('collation', conn.info.collation);
}
case Status.CONNECTING:
case Status.AUTHENTICATING:
const errAuth = Errors.createFatalError(
'Connection is already connecting',
Errors.ER_ALREADY_CONNECTING,
this.info
);
if (this.opts.logger.error) this.opts.logger.error(errAuth);
return Promise.reject(errAuth);
}
//status Connected
return Promise.resolve(this);
process.nextTick(conn.nextSendCmd.bind(conn));
});
conn.receiveQueue.push(handshake);
conn.streamInitSocket.call(conn);
});
}
executePromise(values, cmdOpts, prepare, resolve, reject) {
executePromise(cmdParam, prepare, resolve, reject) {
const cmd = new Execute(

@@ -141,18 +146,24 @@ resolve,

}.bind(this),
cmdOpts,
this.opts,
prepare,
values
cmdParam,
prepare
);
if (this.opts.trace) Error.captureStackTrace(cmd);
this.addCommand(cmd);
}
batch(_sql, _options, _values) {
if (!_sql) {
const err = Errors.createError('sql parameter is mandatory', Errors.ER_UNDEFINED_SQL, this.info, 'HY000');
batch(cmdParam) {
if (!cmdParam.sql) {
const err = Errors.createError(
'sql parameter is mandatory',
Errors.ER_UNDEFINED_SQL,
this.info,
'HY000',
null,
false,
cmdParam.stack
);
if (this.opts.logger.error) this.opts.logger.error(err);
return Promise.reject(err);
}
if (!_values) {
if (!cmdParam.values) {
const err = Errors.createError(

@@ -163,3 +174,5 @@ 'Batch must have values set',

'HY000',
_sql
cmdParam.sql,
false,
cmdParam.stack
);

@@ -170,29 +183,29 @@ if (this.opts.logger.error) this.opts.logger.error(err);

return new Promise(this.prepare.bind(this, _options, _sql, this.executePromise.bind(this))).then((prepare) => {
const usePlaceHolder = (_options && _options.namedPlaceholders) || this.opts.namedPlaceholders;
return new Promise(this.prepare.bind(this, cmdParam, this.executePromise.bind(this))).then((prepare) => {
const usePlaceHolder = (cmdParam.opts && cmdParam.opts.namedPlaceholders) || this.opts.namedPlaceholders;
let vals;
if (Array.isArray(_values)) {
if (Array.isArray(cmdParam.values)) {
if (usePlaceHolder) {
vals = _values;
} else if (Array.isArray(_values[0])) {
vals = _values;
vals = cmdParam.values;
} else if (Array.isArray(cmdParam.values[0])) {
vals = cmdParam.values;
} else if (prepare.parameters.length === 1) {
vals = [];
for (let i = 0; i < _values.length; i++) {
vals.push([_values[i]]);
for (let i = 0; i < cmdParam.values.length; i++) {
vals.push([cmdParam.values[i]]);
}
} else {
vals = [_values];
vals = [cmdParam.values];
}
} else {
vals = [[_values]];
vals = [[cmdParam.values]];
}
let useBulk = this._canUseBulk(vals, _options);
cmdParam.values = vals;
let useBulk = this._canUseBulk(vals, cmdParam.opts);
if (useBulk) {
return new Promise(this.executeBulkPromise.bind(this, vals, _options, prepare));
return new Promise(this.executeBulkPromise.bind(this, cmdParam, prepare));
} else {
const executes = [];
for (let i = 0; i < vals.length; i++) {
executes.push(prepare.execute(vals[i], _options));
executes.push(prepare.execute(vals[i], cmdParam.opts, null, cmdParam.stack));
}

@@ -202,3 +215,3 @@ return Promise.all(executes).then(

prepare.close();
if (_options && _options.fullResult) {
if (cmdParam.opts && cmdParam.opts.fullResult) {
return Promise.resolve(res);

@@ -227,3 +240,2 @@ } else {

}
return;
}

@@ -236,3 +248,3 @@ }.bind(this)

executeBulkPromise(values, cmdOpts, prepare, resolve, reject) {
executeBulkPromise(cmdParam, prepare, resolve, reject) {
const cmd = new BatchBulk(

@@ -247,8 +259,6 @@ (res) => {

}.bind(this),
cmdOpts,
this.opts,
prepare,
values
cmdParam
);
if (this.opts.trace) Error.captureStackTrace(cmd);
this.addCommand(cmd);

@@ -259,7 +269,7 @@ }

* Send an empty MySQL packet to ensure connection is active, and reset @@wait_timeout
* @param timeout (optional) timeout value in ms. If reached, throw error and close connection
* @param cmdParam command context
*/
ping(timeout, resolve, reject) {
if (timeout) {
if (timeout < 0) {
ping(cmdParam, resolve, reject) {
if (cmdParam.opts && cmdParam.opts.timeout) {
if (cmdParam.opts.timeout < 0) {
const err = Errors.createError(

@@ -291,6 +301,7 @@ 'Ping cannot have negative timeout value',

}.bind(this),
timeout
cmdParam.opts.timeout
);
this.addCommand(
new Ping(
cmdParam,
() => {

@@ -311,3 +322,3 @@ if (tOut) {

}
this.addCommand(new Ping(resolve, reject));
this.addCommand(new Ping(cmdParam, resolve, reject));
}

@@ -323,6 +334,4 @@

* - remove all PREPARE statement
*
* @returns {Promise} promise
*/
reset(resolve, reject) {
reset(cmdParam, resolve, reject) {
if (

@@ -332,3 +341,3 @@ (this.info.isMariaDB() && this.info.hasMinVersion(10, 2, 4)) ||

) {
const resetCmd = new Reset(resolve, reject);
const resetCmd = new Reset(cmdParam, resolve, reject);
this.addCommand(resetCmd);

@@ -341,2 +350,3 @@ return;

);
err.stack = cmdParam.stack;
if (this.opts.logger.error) this.opts.logger.error(err);

@@ -357,3 +367,3 @@ reject(err);

*/
end(resolve, reject) {
end(cmdParam, resolve, reject) {
this.addCommand = this.addCommandDisabled;

@@ -372,3 +382,3 @@ clearTimeout(this.timeout);

};
const quitCmd = new Quit(ended, ended);
const quitCmd = new Quit(cmdParam, ended, ended);
this.sendQueue.push(quitCmd);

@@ -399,7 +409,7 @@ this.receiveQueue.push(quitCmd);

.connect()
.then(function () {
.then(() => {
//*************************************************
//kill connection
//*************************************************
const killResHandler = function (err) {
new Promise(killCon.query.bind(killCon, null, `KILL ${self.info.threadId}`, undefined)).finally((err) => {
const destroyError = Errors.createFatalError(

@@ -412,11 +422,14 @@ 'Connection destroyed, command was killed',

self.socketErrorDispatchToQueries(destroyError);
if (self.socket) process.nextTick(self.socket.destroy());
if (self.socket) {
const sok = self.socket;
process.nextTick(() => {
sok.destroy();
});
}
self.status = Status.CLOSED;
self.clear();
new Promise(killCon.end.bind(killCon)).catch(() => {});
};
new Promise(killCon.query.bind(killCon, null, `KILL ${self.info.threadId}`, undefined)).finally(
killResHandler
);
});
})
.catch((err) => {
.catch(() => {
//*************************************************

@@ -429,3 +442,2 @@ //failing to create a kill connection, end normally

self.status = Status.CLOSED;
setImmediate(resolve);
sock.destroy();

@@ -444,5 +456,5 @@ self.receiveQueue.clear();

this.socket.destroy();
this.clear();
}
}
this.clear();
}

@@ -590,41 +602,2 @@

/**
* Add handshake command to queue.
*
* @private
*/
registerHandshakeCmd(resolve, rejected) {
const _authFail = this.authFailHandler.bind(
this,
function (err) {
if (this.opts.logger.error) this.opts.logger.error(err);
rejected(err);
}.bind(this)
);
const _authSucceed = this.authSucceedHandler.bind(this, resolve, _authFail);
const handshake = new Handshake(
_authSucceed,
_authFail,
this.createSecureContext.bind(this, _authFail),
this.addCommandEnable.bind(this),
this.getSocket.bind(this)
);
Error.captureStackTrace(handshake);
handshake.once(
'end',
function () {
if (!this.opts.collation) {
this.opts.emit('collation', this.info.collation);
}
process.nextTick(this.nextSendCmd.bind(this));
}.bind(this)
);
this.receiveQueue.push(handshake);
this.streamInitSocket(_authFail);
}
executeSessionVariableQuery() {

@@ -636,26 +609,20 @@ if (this.opts.sessionVariables) {

if (keys.length > 0) {
return new Promise(
function (resolve, reject) {
for (let k = 0; k < keys.length; ++k) {
sessionQuery += (k !== 0 ? ',' : '') + '@@' + keys[k].replace(/[^a-z0-9_]/gi, '') + '=?';
values.push(this.opts.sessionVariables[keys[k]]);
}
const errorHandling = (initialErr) => {
const err = Errors.createFatalError(
`Error setting session variable (value ${JSON.stringify(this.opts.sessionVariables)}). Error: ${
initialErr.message
}`,
Errors.ER_SETTING_SESSION_ERROR,
this.info,
'08S01',
sessionQuery
);
if (this.opts.logger.error) this.opts.logger.error(err);
reject(err);
};
const cmd = new Query(resolve, errorHandling, null, this.opts, sessionQuery, values);
if (this.opts.trace) Error.captureStackTrace(cmd);
this.addCommand(cmd);
}.bind(this)
);
for (let k = 0; k < keys.length; ++k) {
sessionQuery += (k !== 0 ? ',' : '') + '@@' + keys[k].replace(/[^a-z0-9_]/gi, '') + '=?';
values.push(this.opts.sessionVariables[keys[k]]);
}
return new Promise(this.query.bind(this, new CommandParameter(sessionQuery, values))).catch((initialErr) => {
const err = Errors.createFatalError(
`Error setting session variable (value ${JSON.stringify(this.opts.sessionVariables)}). Error: ${
initialErr.message
}`,
Errors.ER_SETTING_SESSION_ERROR,
this.info,
'08S01',
sessionQuery
);
if (this.opts.logger.error) this.opts.logger.error(err);
return Promise.reject(err);
});
}

@@ -673,27 +640,27 @@ }

if (this.opts.timezone === 'auto') {
return new Promise(this.query.bind(this, null, 'SELECT @@system_time_zone stz, @@time_zone tz', undefined)).then(
(res) => {
const serverTimezone = res[0].tz === 'SYSTEM' ? res[0].stz : res[0].tz;
const serverZone = moment.tz.zone(serverTimezone);
if (serverZone) {
const localTz = moment.tz.guess();
if (serverTimezone === localTz) {
//db server and client use same timezone, avoid any conversion
this.opts.tz = null;
} else {
this.opts._localTz = localTz;
this.opts.tz = serverTimezone;
}
return new Promise(
this.query.bind(this, new CommandParameter('SELECT @@system_time_zone stz, @@time_zone tz'))
).then((res) => {
const serverTimezone = res[0].tz === 'SYSTEM' ? res[0].stz : res[0].tz;
const serverZone = moment.tz.zone(serverTimezone);
if (serverZone) {
const localTz = moment.tz.guess();
if (serverTimezone === localTz) {
//db server and client use same timezone, avoid any conversion
this.opts.tz = null;
} else {
const err = Errors.createFatalError(
`Automatic timezone setting fails. Server timezone '${serverTimezone}' does't have a corresponding IANA timezone. Option timezone must be set according to server timezone`,
Errors.ER_WRONG_AUTO_TIMEZONE,
this.info
);
if (this.opts.logger.error) this.opts.logger.error(err);
return Promise.reject(err);
this.opts._localTz = localTz;
this.opts.tz = serverTimezone;
}
return Promise.resolve();
} else {
const err = Errors.createFatalError(
`Automatic timezone setting fails. Server timezone '${serverTimezone}' doesn't have a corresponding IANA timezone. Option timezone must be set according to server timezone`,
Errors.ER_WRONG_AUTO_TIMEZONE,
this.info
);
if (this.opts.logger.error) this.opts.logger.error(err);
return Promise.reject(err);
}
);
return Promise.resolve();
});
}

@@ -708,13 +675,9 @@ if (this.opts.tz && !this.opts.skipSetTimezone) {

}
return new Promise(this.query.bind(this, null, 'SET time_zone=?', [tz]))
.then(() => {
return Promise.resolve();
})
.catch((err) => {
if (this.opts.logger.error) this.opts.logger.error(err);
console.log(
`warning: setting timezone '${this.opts.tz}' fails on server.\n look at https://mariadb.com/kb/en/mysql_tzinfo_to_sql/ to load IANA timezone.\nSetting timezone can be disabled with option \`skipSetTimezone\``
);
return Promise.resolve();
});
return new Promise(this.query.bind(this, new CommandParameter('SET time_zone=?', [tz]))).catch((err) => {
if (this.opts.logger.error) this.opts.logger.error(err);
console.log(
`warning: setting timezone '${this.opts.tz}' fails on server.\n look at https://mariadb.com/kb/en/mysql_tzinfo_to_sql/ to load IANA timezone.\nSetting timezone can be disabled with option \`skipSetTimezone\``
);
return Promise.resolve();
});
}

@@ -728,3 +691,3 @@ return Promise.resolve();

}
return new Promise(this.query.bind(this, null, 'SELECT @@VERSION AS v', undefined)).then(
return new Promise(this.query.bind(this, new CommandParameter('SELECT @@VERSION AS v'))).then(
function (res) {

@@ -744,3 +707,3 @@ this.info.serverVersion.raw = res[0].v;

initialArr.forEach((sql) => {
initialPromises.push(new Promise(this.query.bind(this, null, sql, undefined)));
initialPromises.push(new Promise(this.query.bind(this, new CommandParameter(sql))));
});

@@ -765,3 +728,3 @@

const query = `SET max_statement_time=${this.opts.queryTimeout / 1000}`;
new Promise(this.query.bind(this, null, query, undefined)).catch(
new Promise(this.query.bind(this, new CommandParameter(query))).catch(
function (initialErr) {

@@ -802,3 +765,3 @@ const err = Errors.createFatalError(

*/
streamInitSocket(authFailHandler) {
streamInitSocket() {
if (this.opts.socketPath) {

@@ -811,11 +774,7 @@ this.socket = Net.connect(this.opts.socketPath);

if (err) {
authFailHandler(err);
this.authFailHandler(err);
return;
} else if (stream) {
this.socket = stream;
this.socketInit(authFailHandler);
} else {
this.socket = Net.connect(this.opts.port, this.opts.host);
this.socketInit(authFailHandler);
}
this.socket = stream ? stream : Net.connect(this.opts.port, this.opts.host);
this.socketInit();
}.bind(this)

@@ -825,11 +784,12 @@ );

this.socket = tmpSocket;
this.socketInit(authFailHandler);
this.socketInit();
}
} else {
const err = Errors.createError(
'stream option is not a function. stream must be a function with (error, callback) parameter',
Errors.ER_BAD_PARAMETER_VALUE,
this.info
this.authFailHandler(
Errors.createError(
'stream option is not a function. stream must be a function with (error, callback) parameter',
Errors.ER_BAD_PARAMETER_VALUE,
this.info
)
);
authFailHandler(err);
}

@@ -840,21 +800,13 @@ return;

}
this.socketInit(authFailHandler);
this.socketInit();
}
socketInit(authFailHandler) {
socketInit() {
if (this.opts.connectTimeout) {
this.timeout = setTimeout(
this.connectTimeoutReached.bind(this),
this.opts.connectTimeout,
authFailHandler,
Date.now()
);
this.timeout = setTimeout(this.connectTimeoutReached.bind(this), this.opts.connectTimeout, Date.now());
}
const socketError = this.socketErrorHandler.bind(this, authFailHandler);
this.socket.on('data', this.streamIn.onData.bind(this.streamIn));
this.socket.on('error', socketError);
this.socket.on('end', socketError);
this.socket.on('error', this.socketErrorHandler.bind(this));
this.socket.on('end', this.socketErrorHandler.bind(this));
this.socket.on(

@@ -866,4 +818,3 @@ 'connect',

this.status = Status.AUTHENTICATING;
this.socketConnected = true;
this.socket.setTimeout(this.opts.socketTimeout, this.socketTimeoutReached.bind(this, authFailHandler));
this.socket.setTimeout(this.opts.socketTimeout, this.socketTimeoutReached.bind(this));
this.socket.setNoDelay(true);

@@ -889,3 +840,3 @@

*/
authSucceedHandler(resolve, rejected) {
authSucceedHandler() {
//enable packet compression according to option

@@ -898,9 +849,10 @@ if (this.opts.compress) {

this.socket.on('data', this.streamIn.onData.bind(this.streamIn));
} else {
const err = Errors.createError(
"connection is configured to use packet compression, but the server doesn't have this capability",
Errors.ER_COMPRESSION_NOT_SUPPORTED,
this.info
} else if (this.opts.logger.error) {
this.opts.logger.error(
Errors.createError(
"connection is configured to use packet compression, but the server doesn't have this capability",
Errors.ER_COMPRESSION_NOT_SUPPORTED,
this.info
)
);
if (this.opts.logger.error) this.opts.logger.error(err);
}

@@ -915,11 +867,3 @@ }

});
const errorInitialQueries = (err) => {
if (!err.fatal)
this.end(
() => {},
() => {}
);
process.nextTick(rejected, err);
};
const conn = this;
this.status = Status.INIT_CMD;

@@ -931,9 +875,19 @@ this.executeSessionVariableQuery()

.then(this.executeSessionTimeout.bind(this))
.then(
function () {
this.status = Status.CONNECTED;
process.nextTick(resolve, this);
}.bind(this)
)
.catch(errorInitialQueries);
.then(() => {
conn.status = Status.CONNECTED;
process.nextTick(conn.connectResolveFct, conn);
conn.connectRejectFct = null;
conn.connectResolveFct = null;
})
.catch((err) => {
if (!err.fatal) {
const res = () => {
conn.authFailHandler.call(conn, err);
};
conn.end(res, res);
} else {
conn.authFailHandler.call(conn, err);
}
});
}

@@ -946,8 +900,12 @@

*/
authFailHandler(reject, err) {
process.nextTick(reject, err);
//remove handshake command
this.receiveQueue.shift();
authFailHandler(err) {
if (this.connectRejectFct) {
if (this.opts.logger.error) this.opts.logger.error(err);
//remove handshake command
this.receiveQueue.shift();
this.fatalError(err, true);
this.fatalError(err, true);
process.nextTick(this.connectRejectFct, err);
this.connectRejectFct = null;
}
}

@@ -958,14 +916,6 @@

*
* @param rejected rejected function when error
* @param callback callback function when done
* @private
*/
createSecureContext(rejected, callback) {
const socketError = this.socketErrorHandler.bind(
this,
function (err) {
if (this.opts.logger.error) this.opts.logger.error(err);
rejected(err);
}.bind(this)
);
createSecureContext(callback) {
const sslOption = Object.assign({}, this.opts.ssl, {

@@ -980,4 +930,4 @@ servername: this.opts.host,

secureSocket.on('data', this.streamIn.onData.bind(this.streamIn));
secureSocket.on('error', socketError);
secureSocket.on('end', socketError);
secureSocket.on('error', this.socketErrorHandler.bind(this));
secureSocket.on('end', this.socketErrorHandler.bind(this));
secureSocket.writeBuf = (buf) => secureSocket.write(buf);

@@ -991,3 +941,3 @@ secureSocket.flush = () => {};

} catch (err) {
socketError(err);
this.socketErrorHandler(err);
}

@@ -1035,3 +985,3 @@ }

*/
connectTimeoutReached(authFailHandler, initialConnectionTime) {
connectTimeoutReached(initialConnectionTime) {
this.timeout = null;

@@ -1048,3 +998,3 @@ const handshake = this.receiveQueue.peekFront();

if (this.opts.logger.error) this.opts.logger.error(err);
authFailHandler(err);
this.authFailHandler(err);
}

@@ -1153,7 +1103,6 @@

*
* @param authFailHandler authentication handler
* @param err socket error
* @private
*/
socketErrorHandler(authFailHandler, err) {
socketErrorHandler(err) {
if (this.status >= Status.CLOSING) return;

@@ -1174,3 +1123,3 @@ if (this.socket) {

err.fatal = true;
this.sqlState = 'HY000';
err.sqlState = 'HY000';
}

@@ -1185,3 +1134,3 @@

}
authFailHandler(err);
this.authFailHandler(err);
break;

@@ -1248,3 +1197,3 @@

errorThrownByCmd = true;
setImmediate(receiveCmd.throwError.bind(receiveCmd), err, this.info);
setImmediate(receiveCmd.throwError.bind(receiveCmd, err, this.info));
}

@@ -1282,3 +1231,3 @@ }

*/
changeTransaction(sql, resolve, reject) {
changeTransaction(cmdParam, resolve, reject) {
//if command in progress, driver cannot rely on status and must execute query

@@ -1291,3 +1240,3 @@ if (this.status >= Status.CLOSING) {

'08S01',
sql
cmdParam.sql
);

@@ -1307,8 +1256,5 @@ if (this.opts.logger.error) this.opts.logger.error(err);

},
null,
this.opts,
sql,
null
cmdParam
);
if (this.opts.trace) Error.captureStackTrace(cmd);
this.addCommand(cmd);

@@ -1318,3 +1264,3 @@ } else resolve();

changeUser(options, resolve, reject) {
changeUser(cmdParam, resolve, reject) {
if (!this.info.isMariaDB()) {

@@ -1334,12 +1280,9 @@ const err = Errors.createError(

new ChangeUser(
options,
cmdParam,
this.opts,
(res) => {
if (options && options.collation) this.opts.collation = options.collation;
if (cmdParam.opts && cmdParam.opts.collation) this.opts.collation = cmdParam.opts.collation;
resolve(res);
},
this.authFailHandler.bind(this, (err) => {
if (this.opts.logger.error) this.opts.logger.error(err);
reject(err);
}),
this.authFailHandler.bind(this, reject),
this.addCommand.bind(this)

@@ -1350,5 +1293,15 @@ )

query(_cmdOpt, _sql, _values, resolve, reject) {
if (!_sql)
return reject(Errors.createError('sql parameter is mandatory', Errors.ER_UNDEFINED_SQL, this.info, 'HY000'));
query(cmdParam, resolve, reject) {
if (!cmdParam.sql)
return reject(
Errors.createError(
'sql parameter is mandatory',
Errors.ER_UNDEFINED_SQL,
this.info,
'HY000',
null,
false,
cmdParam.stack
)
);
const cmd = new Query(

@@ -1360,14 +1313,10 @@ resolve,

},
_cmdOpt,
this.opts,
_sql,
_values
cmdParam
);
if (this.opts.trace) Error.captureStackTrace(cmd);
this.addCommand(cmd);
}
prepare(_cmdOpt, _sql, executeFct, resolve, reject) {
if (!_sql)
prepare(cmdParam, executeFct, resolve, reject) {
if (!cmdParam.sql)
return reject(Errors.createError('sql parameter is mandatory', Errors.ER_UNDEFINED_SQL, this.info, 'HY000'));

@@ -1380,9 +1329,7 @@ const cmd = new Prepare(

},
_cmdOpt,
this.opts,
_sql,
cmdParam,
executeFct,
this
);
if (this.opts.trace) Error.captureStackTrace(cmd);
this.addCommand(cmd);

@@ -1389,0 +1336,0 @@ }

@@ -17,3 +17,3 @@ // noinspection SpellCheckingInspection

static fromCharset(charset) {
return defaultCharsets[charset];
return defaultCharsets[charset == 'utf8mb3' ? 'utf8' : charset];
}

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

@@ -45,7 +45,7 @@ /**

.then((res) => {
conn.end();
conn.release();
return res;
})
.catch((err) => {
conn.end();
conn.release();
return Promise.reject(err);

@@ -74,7 +74,7 @@ });

.then((res) => {
conn.end();
conn.release();
return res;
})
.catch((err) => {
conn.end();
conn.release();
return Promise.reject(err);

@@ -103,7 +103,7 @@ });

.then((res) => {
conn.end();
conn.release();
return res;
})
.catch((err) => {
conn.end();
conn.release();
return Promise.reject(err);

@@ -110,0 +110,0 @@ });

@@ -126,6 +126,5 @@ 'use strict';

if (chunkLen - pos >= length) {
const buf = chunk.slice(pos, pos + length);
pos += length;
if (this.parts) {
this.parts.push(buf);
this.parts.push(chunk.slice(pos - length, pos));
this.partsTotalLen += length;

@@ -140,5 +139,5 @@

if (this.packetLen < 0xffffff) {
this.receivePacket(this.packet.update(buf, 0, length));
this.receivePacket(this.packet.update(chunk, pos - length, pos));
} else {
this.parts = [buf];
this.parts = [chunk.slice(pos - length, pos)];
this.partsTotalLen = length;

@@ -145,0 +144,0 @@ }

@@ -14,3 +14,3 @@ 'use strict';

//increase by level to avoid buffer copy.
const SMALL_BUFFER_SIZE = 1024;
const SMALL_BUFFER_SIZE = 256;
const MEDIUM_BUFFER_SIZE = 16384; //16k

@@ -132,9 +132,11 @@ const LARGE_BUFFER_SIZE = 131072; //128k

this.markPos = -1;
const data = Buffer.allocUnsafe(this.pos - 4);
this.buf.copy(data, 0, 4, this.pos);
this.cmd.sequenceNo = -1;
this.cmd.compressSequenceNo = -1;
this.bufContainDataAfterMark = false;
return data;
if (this.bufContainDataAfterMark) {
const data = Buffer.allocUnsafe(this.pos - 4);
this.buf.copy(data, 0, 4, this.pos);
this.cmd.sequenceNo = -1;
this.cmd.compressSequenceNo = -1;
this.bufContainDataAfterMark = false;
return data;
}
return null;
}

@@ -558,9 +560,2 @@

if (valLen * 2 > this.buf.length - this.pos) {
if (this.markPos !== -1) {
this.growBuffer(valLen * 2);
if (this.markPos !== -1) {
this.flushBufferStopAtMark();
}
}
//not enough space in buffer, will fill buffer

@@ -567,0 +562,0 @@ for (let i = 0; i < valLen; i++) {

@@ -192,2 +192,3 @@ 'use strict';

const type = this.buf[this.pos++] & 0xff;
if (type < 0xfb) return type;
switch (type) {

@@ -203,4 +204,2 @@ case 0xfb:

return Number(this.readBigInt64());
default:
return type;
}

@@ -239,4 +238,5 @@ }

switch (type) {
case 0xfb:
return null;
// null test is not used for now, since only used for reading insertId
// case 0xfb:
// return null;
case 0xfc:

@@ -288,3 +288,3 @@ return BigInt(this.readUInt16());

this.pos += len;
return negate ? -1 * result : result;
return negate ? -1n * result : result;
}

@@ -360,3 +360,3 @@

readBinaryDateTime(opts, col) {
readBinaryDateTime(opts) {
const len = this.buf[this.pos++];

@@ -374,3 +374,3 @@ let year = 0;

if (len > 2) {
month = this.readUInt8() - 1;
month = this.readUInt8();
if (len > 3) {

@@ -391,28 +391,62 @@ day = this.readUInt8();

//handle zero-date as null
if (year === 0 && month === 0 && day === 0 && hour === 0 && min === 0 && sec === 0 && microSec === 0)
return opts.dateStrings
? '0000-00-00 00:00:00' + (col.scale > 0 ? '.000000'.substr(0, col.scale + 1) : '')
: null;
if (year === 0 && month === 0 && day === 0 && hour === 0 && min === 0 && sec === 0 && microSec === 0) return null;
if (opts.dateStrings) {
return (
appendZero(year, 4) +
'-' +
appendZero(month + 1, 2) +
'-' +
appendZero(day, 2) +
' ' +
appendZero(hour, 2) +
':' +
appendZero(min, 2) +
':' +
appendZero(sec, 2) +
(microSec > 0 && col.scale > 0 ? '.' + appendZero(microSec, 6).substr(0, col.scale) : '')
);
if (opts.tz && opts.tz === 'Etc/UTC') {
return new Date(Date.UTC(year, month - 1, day, hour, min, sec, microSec / 1000));
}
return new Date(year, month - 1, day, hour, min, sec, microSec / 1000);
}
if (opts.tz && opts.tz === 'Etc/UTC') {
return new Date(Date.UTC(year, month, day, hour, min, sec, microSec / 1000));
readBinaryDateTimeAsString(scale) {
const len = this.buf[this.pos++];
let year = 0;
let month = 0;
let day = 0;
let hour = 0;
let min = 0;
let sec = 0;
let microSec = 0;
if (len > 0) {
year = this.readInt16();
if (len > 2) {
month = this.readUInt8();
if (len > 3) {
day = this.readUInt8();
if (len > 4) {
hour = this.readUInt8();
min = this.readUInt8();
sec = this.readUInt8();
if (len > 7) {
microSec = this.readUInt32();
}
}
}
}
}
return new Date(year, month, day, hour, min, sec, microSec / 1000);
//handle zero-date as null
if (year === 0 && month === 0 && day === 0 && hour === 0 && min === 0 && sec === 0 && microSec === 0)
return '0000-00-00 00:00:00' + (scale > 0 ? '.000000'.substr(0, scale + 1) : '');
return (
appendZero(year, 4) +
'-' +
appendZero(month, 2) +
'-' +
appendZero(day, 2) +
' ' +
appendZero(hour, 2) +
':' +
appendZero(min, 2) +
':' +
appendZero(sec, 2) +
(microSec > 0
? scale > 0
? '.' + appendZero(microSec, 6).substr(0, scale)
: '.' + appendZero(microSec, 6)
: scale > 0
? '.' + appendZero(microSec, 6).substr(0, scale)
: '')
);
}

@@ -451,5 +485,15 @@

readIntLengthEncoded() {
const len = this.readUnsignedLength();
if (len === null) return null;
return this._atoi(len);
const len = this.buf[this.pos++] & 0xff;
if (len < 0xfb) return this._atoi(len);
switch (len) {
case 0xfb:
return null;
case 0xfc:
return this._atoi(this.readUInt16());
case 0xfd:
return this._atoi(this.readUInt24());
case 0xfe:
// limitation to BigInt signed value
return this._atoi(Number(this.readBigInt64()));
}
}

@@ -536,10 +580,15 @@

let errno = this.readUInt16();
let sqlState = '';
let sqlState;
let msg;
// check '#'
if (this.peek() === 0x23) {
// skip '#'
this.skip(6);
sqlState = this.buf.toString(undefined, this.pos - 5, this.pos);
msg = this.readStringNullEnded();
} else {
// pre 4.1 format
sqlState = 'HY000';
msg = this.buf.toString(undefined, this.pos, this.end);
}
let msg = this.buf.toString(undefined, this.pos, this.end);
let fatal = sqlState.startsWith('08') || sqlState === '70100';

@@ -546,0 +595,0 @@ return Errors.createError(msg, errno, info, sqlState, sql, fatal, stack);

@@ -15,2 +15,3 @@ 'use strict';

);
this.name = 'SqlError';
this.text = msg;

@@ -89,3 +90,2 @@ this.sql = sql;

module.exports.ER_CONNECTION_ALREADY_CLOSED = 45001;
module.exports.ER_ALREADY_CONNECTING = 45002;
module.exports.ER_MYSQL_CHANGE_USER_BUG = 45003;

@@ -128,3 +128,2 @@ module.exports.ER_CMD_NOT_EXECUTED_DESTROYED = 45004;

module.exports.ER_DUPLICATE_FIELD = 45040;
module.exports.ER_CLIENT_OPTION_INCOMPATIBILITY = 45041;
module.exports.ER_PING_TIMEOUT = 45042;

@@ -138,2 +137,3 @@ module.exports.ER_BAD_PARAMETER_VALUE = 45043;

module.exports.ER_UNDEFINED_SQL = 45049;
module.exports.ER_PARSING_PRECISION = 45050;

@@ -140,0 +140,0 @@ const keys = Object.keys(module.exports);

@@ -8,2 +8,3 @@ 'use strict';

const ConnectionCallback = require('./connection-callback');
const CommandParameter = require('./command-parameter');

@@ -19,2 +20,3 @@ class PoolCallback extends EventEmitter {

this.#pool.on('release', this.emit.bind(this, 'release'));
this.#pool.on('error', this.emit.bind(this, 'error'));
}

@@ -93,21 +95,11 @@

}
const cmdParam = new CommandParameter();
if (this.#pool.opts.connOptions.trace) Error.captureStackTrace(cmdParam);
this.#pool
.getConnection()
.getConnection(cmdParam)
.then((baseConn) => {
const conn = new ConnectionCallback(baseConn);
conn.release = function () {
return new Promise(baseConn.release);
};
conn.release = (cb) => {
baseConn.release(
() => {
if (cb) cb();
},
(err) => {
if (cb) cb(err);
}
);
};
conn.end = conn.release;
cb(null, conn);
const cc = new ConnectionCallback(baseConn);
cc.end = (cb) => cc.release(cb);
cc.close = (cb) => cc.release(cb);
cb(null, cc);
})

@@ -127,20 +119,15 @@ .catch(cb);

query(sql, values, cb) {
let _cb = cb,
_values = values;
if (typeof values === 'function') {
_cb = values;
_values = undefined;
}
const cmdParam = ConnectionCallback._PARAM(this.#pool.opts.connOptions, sql, values, cb);
this.#pool
.getConnection()
.getConnection(cmdParam)
.then((baseConn) => {
ConnectionCallback._QUERY_CMD(baseConn, sql, _values, (err, rows, meta) => {
const _cb = cmdParam.callback;
cmdParam.callback = (err, rows, meta) => {
this.#pool.release(baseConn);
if (_cb) _cb(err, rows, meta);
});
};
ConnectionCallback._QUERY_CMD(baseConn, cmdParam);
})
.catch((err) => {
if (_cb) _cb(err);
if (cmdParam.callback) cmdParam.callback(err);
});

@@ -159,20 +146,16 @@ }

execute(sql, values, cb) {
let _cb = cb,
_values = values;
const cmdParam = ConnectionCallback._PARAM(this.#pool.opts.connOptions, sql, values, cb);
if (typeof values === 'function') {
_cb = values;
_values = undefined;
}
this.#pool
.getConnection()
.getConnection(cmdParam)
.then((baseConn) => {
ConnectionCallback._EXECUTE_CMD(baseConn, sql, _values, (err, rows, meta) => {
const _cb = cmdParam.callback;
cmdParam.callback = (err, rows, meta) => {
this.#pool.release(baseConn);
if (_cb) _cb(err, rows, meta);
});
};
ConnectionCallback._EXECUTE_CMD(baseConn, cmdParam);
})
.catch((err) => {
if (_cb) _cb(err);
if (cmdParam.callback) cmdParam.callback(err);
});

@@ -190,20 +173,15 @@ }

batch(sql, values, cb) {
let _values = values,
_cb = cb;
if (typeof values === 'function') {
_cb = values;
_values = undefined;
}
const cmdParam = ConnectionCallback._PARAM(this.#pool.opts.connOptions, sql, values, cb);
this.#pool
.getConnection()
.getConnection(cmdParam)
.then((baseConn) => {
ConnectionCallback._BATCH_CMD(baseConn, sql, _values, (err, rows, meta) => {
const _cb = cmdParam.callback;
cmdParam.callback = (err, rows, meta) => {
this.#pool.release(baseConn);
if (_cb) _cb(err, rows, meta);
});
};
ConnectionCallback._BATCH_CMD(baseConn, cmdParam);
})
.catch((err) => {
if (_cb) _cb(err);
if (cmdParam.callback) cmdParam.callback(err);
});

@@ -210,0 +188,0 @@ }

@@ -7,2 +7,3 @@ 'use strict';

const ConnectionPromise = require('./connection-promise');
const CommandParameter = require('./command-parameter');

@@ -18,2 +19,3 @@ class PoolPromise extends EventEmitter {

this.#pool.on('release', this.emit.bind(this, 'release'));
this.#pool.on('error', this.emit.bind(this, 'error'));
}

@@ -81,3 +83,5 @@

getConnection() {
return this.#pool.getConnection().then((baseConn) => {
const cmdParam = new CommandParameter();
if (this.#pool.opts.connOptions.trace) Error.captureStackTrace(cmdParam);
return this.#pool.getConnection(cmdParam).then((baseConn) => {
const conn = new ConnectionPromise(baseConn);

@@ -87,2 +91,4 @@ conn.release = function () {

};
conn.end = conn.release;
conn.close = conn.release;
return conn;

@@ -101,4 +107,5 @@ });

query(sql, values) {
return this.#pool.getConnection().then((baseConn) => {
return ConnectionPromise._QUERY_CMD(baseConn, sql, values).finally(() => {
const cmdParam = ConnectionPromise._PARAM(this.#pool.opts.connOptions, sql, values);
return this.#pool.getConnection(cmdParam).then((baseConn) => {
return new Promise(baseConn.query.bind(baseConn, cmdParam)).finally(() => {
this.#pool.release(baseConn);

@@ -118,4 +125,5 @@ });

execute(sql, values) {
return this.#pool.getConnection().then((baseConn) => {
return ConnectionPromise._EXECUTE_CMD(baseConn, sql, values).finally(() => {
const cmdParam = ConnectionPromise._PARAM(this.#pool.opts.connOptions, sql, values);
return this.#pool.getConnection(cmdParam).then((baseConn) => {
return ConnectionPromise._EXECUTE_CMD(baseConn, cmdParam).finally(() => {
this.#pool.release(baseConn);

@@ -134,4 +142,5 @@ });

batch(sql, values) {
return this.#pool.getConnection().then((baseConn) => {
return ConnectionPromise._BATCH_CMD(baseConn, sql, values).finally(() => {
const cmdParam = ConnectionPromise._PARAM(this.#pool.opts.connOptions, sql, values);
return this.#pool.getConnection(cmdParam).then((baseConn) => {
return ConnectionPromise._BATCH_CMD(baseConn, cmdParam).finally(() => {
this.#pool.release(baseConn);

@@ -138,0 +147,0 @@ });

@@ -9,7 +9,9 @@ 'use strict';

const Connection = require('./connection');
const CommandParameter = require('./command-parameter');
class Pool extends EventEmitter {
#opts;
opts;
#closed = false;
#connectionInCreation = false;
#errorCreatingConnection = null;
#idleConnections = new Queue();

@@ -21,2 +23,3 @@ #activeConnections = {};

#connErrorNumber = 0;
#initialized = false;
_sizeHandlerTimeout;

@@ -26,3 +29,3 @@

super();
this.#opts = options;
this.opts = options;

@@ -44,9 +47,13 @@ this.on('_idle', this._requestsHandler);

conn.forceEnd(
null,
() => {},
() => {}
);
throw new Errors.createFatalError(
'Cannot create new connection to pool, pool closed',
Errors.ER_ADD_CONNECTION_CLOSED_POOL
reject(
new Errors.createFatalError(
'Cannot create new connection to pool, pool closed',
Errors.ER_ADD_CONNECTION_CLOSED_POOL
)
);
return;
}

@@ -73,7 +80,7 @@

pool.#idleConnections.removeOne(idx);
break;
continue;
}
//since connection did have an error, other waiting connection might too
//forcing validation when borrowed next time, even if "minDelayValidation" is not reached.
currConn.lastUse = Math.min(currConn.lastUse, Date.now() - pool.#opts.minDelayValidation);
currConn.lastUse = Math.min(currConn.lastUse, Date.now() - pool.opts.minDelayValidation);
idx++;

@@ -101,6 +108,7 @@ }

) {
err.message = err.message + this._errorMsgAddon();
reject(err);
return;
}
setTimeout(this._doCreateConnection.bind(this), 500, resolve, reject, timeoutEnd);
setTimeout(this._doCreateConnection.bind(this, resolve, reject, timeoutEnd), 500);
});

@@ -112,5 +120,5 @@ }

delete this.#activeConnections[conn.threadId];
conn.lastUse = Date.now();
conn.forceEnd(
null,
() => {},

@@ -128,23 +136,21 @@ () => {}

release(conn) {
this._endLeak(conn);
delete this.#activeConnections[conn.threadId];
// ensure releasing only once
if (this.#activeConnections[conn.threadId]) {
this._endLeak(conn);
this.#activeConnections[conn.threadId] = null;
conn.lastUse = Date.now();
conn.lastUse = Date.now();
if (this.#closed) {
conn.forceEnd(
() => {},
() => {}
);
this.emit('validateSize');
} else if (conn.isValid()) {
this.emit('release', conn);
this.#idleConnections.push(conn);
process.nextTick(
function () {
this.emit('_idle');
}.bind(this)
);
} else {
this.emit('validateSize');
if (this.#closed) {
conn.forceEnd(
null,
() => {},
() => {}
);
} else if (conn.isValid()) {
this.emit('release', conn);
this.#idleConnections.push(conn);
process.nextTick(this.emit.bind(this, '_idle'));
} else {
this.emit('validateSize');
}
}

@@ -158,10 +164,12 @@ }

(conn) => {
conn.leaked = true;
console.log(
`Possible connection leak on thread ${conn.info.threadId} (connection not returned to pool since ${
`A possible connection leak on the thread ${
conn.info.threadId
} (the connection not returned to the pool since ${
Date.now() - conn.lastUse
}ms. Did connection.released() been implemented`
} ms). Has the connection.release() been called ?` + this._errorMsgAddon()
);
conn.leaked = true;
},
this.#opts.leakDetectionTimeout,
this.opts.leakDetectionTimeout,
conn

@@ -185,3 +193,3 @@ );

_startReaping() {
if (!this.#unusedConnectionRemoverId && this.#opts.idleTimeout > 0) {
if (!this.#unusedConnectionRemoverId && this.opts.idleTimeout > 0) {
this.#unusedConnectionRemoverId = setInterval(this._reaper.bind(this), 500);

@@ -198,4 +206,4 @@ }

_reaper() {
const idleTimeRemoval = Date.now() - this.#opts.idleTimeout * 1000;
let maxRemoval = Math.max(0, this.#idleConnections.length - this.#opts.minimumIdle);
const idleTimeRemoval = Date.now() - this.opts.idleTimeout * 1000;
let maxRemoval = Math.max(0, this.#idleConnections.length - this.opts.minimumIdle);
while (maxRemoval > 0) {

@@ -207,2 +215,3 @@ const conn = this.#idleConnections.peek();

conn.forceEnd(
null,
() => {},

@@ -225,4 +234,4 @@ () => {}

!this.#connectionInCreation &&
this.#idleConnections.length < this.#opts.minimumIdle &&
this.totalConnections() < this.#opts.connectionLimit &&
this.#idleConnections.length < this.opts.minimumIdle &&
this.totalConnections() < this.opts.connectionLimit &&
!this.#closed

@@ -240,3 +249,3 @@ );

function () {
const timeoutEnd = Date.now() + this.#opts.initializationTimeout;
const timeoutEnd = Date.now() + this.opts.initializationTimeout;
new Promise((resolve, reject) => {

@@ -246,2 +255,4 @@ this._doCreateConnection(resolve, reject, timeoutEnd);

.then(() => {
this.#initialized = true;
this.#errorCreatingConnection = null;
this.#connErrorNumber = 0;

@@ -255,21 +266,22 @@ if (this._shouldCreateMoreConnections()) {

this.#connectionInCreation = false;
if (this.totalConnections() === 0) {
const task = this.#requests.shift();
if (task) {
this._rejectTask(task, err);
if (!this.#closed) {
if (!this.#initialized) {
err.message = 'Error during pool initialization: ' + err.message;
} else {
err.message = 'Pool fails to create connection: ' + err.message;
}
} else if (!this.#closed) {
console.error(`pool fail to create connection (${err.message})`);
this.#errorCreatingConnection = err;
this.emit('error', err);
//delay next try
this._sizeHandlerTimeout = setTimeout(
function () {
this._sizeHandlerTimeout = null;
if (!this.#requests.isEmpty()) {
this._sizeHandler();
}
}.bind(this),
Math.min(++this.#connErrorNumber * 500, 10000)
);
}
//delay next try
this._sizeHandlerTimeout = setTimeout(
function () {
this._sizeHandlerTimeout = null;
if (!this.#requests.isEmpty()) {
this._sizeHandler();
}
}.bind(this),
Math.min(++this.#connErrorNumber * 500, 10000)
);
});

@@ -291,3 +303,3 @@ }.bind(this)

if (conn) {
if (this.#opts.leakDetectionTimeout > 0) this._checkLeak(conn);
if (this.opts.leakDetectionTimeout > 0) this._checkLeak(conn);
this.emit('acquire', conn);

@@ -313,27 +325,28 @@ this.#activeConnections[conn.threadId] = conn;

*/
_doAcquire() {
async _doAcquire() {
if (!this._hasIdleConnection() || this.#closed) return Promise.reject();
const conn = this.#idleConnections.shift();
this.#activeConnections[conn.threadId] = conn;
if (this.#opts.minDelayValidation <= 0 || Date.now() - conn.lastUse > this.#opts.minDelayValidation) {
return new Promise(conn.ping.bind(conn, this.#opts.pingTimeout)).then(
() => {
if (this.#opts.leakDetectionTimeout > 0) this._checkLeak(conn);
return Promise.resolve(conn);
},
() => {
delete this.#activeConnections[conn.threadId];
this.emit('validateSize');
return this._doAcquire();
let conn;
let mustRecheckSize = false;
while ((conn = this.#idleConnections.shift()) != null) {
//just check connection state first
if (conn.isValid()) {
this.#activeConnections[conn.threadId] = conn;
//if not used for some time, validate connection with a COM_PING
if (this.opts.minDelayValidation <= 0 || Date.now() - conn.lastUse > this.opts.minDelayValidation) {
try {
const cmdParam = new CommandParameter(null, null, { timeout: this.opts.pingTimeout });
await new Promise(conn.ping.bind(conn, cmdParam));
} catch (e) {
delete this.#activeConnections[conn.threadId];
continue;
}
}
);
} else {
//just check connection state
if (conn.isValid()) {
if (this.#opts.leakDetectionTimeout > 0) this._checkLeak(conn);
if (this.opts.leakDetectionTimeout > 0) this._checkLeak(conn);
if (mustRecheckSize) setImmediate(this.emit.bind(this, 'validateSize'));
return Promise.resolve(conn);
}
mustRecheckSize = true;
}
setImmediate(this.emit.bind(this, 'validateSize'));
return Promise.reject();
}

@@ -349,10 +362,21 @@

this.#requests.shift();
request.reject(
Errors.createError(
`retrieve connection from pool timeout after ${Math.abs(
Date.now() - (request.timeout - this.#opts.acquireTimeout)
)}ms`,
Errors.ER_GET_CONNECTION_TIMEOUT
)
let err = Errors.createError(
`retrieve connection from pool timeout after ${Math.abs(
Date.now() - (request.timeout - this.opts.acquireTimeout)
)}ms${this._errorMsgAddon()}`,
Errors.ER_GET_CONNECTION_TIMEOUT,
null,
'HY000',
null,
false,
request.stack
);
// in order to provide more information when configuration is wrong / server is down
if (this.activeConnections() == 0 && this.#errorCreatingConnection) {
const errConnMsg = this.#errorCreatingConnection.message.split('\n')[0];
err.message = err.message + `\n connection error: ${errConnMsg}`;
}
request.reject(err);
} else {

@@ -373,7 +397,12 @@ this.#requestTimeoutId = setTimeout(this._requestTimeoutHandler.bind(this), request.timeout - currTime);

if (conn == null) {
conn = Object.keys(this.#activeConnections)[0];
if (!conn) {
for (const threadId in Object.keys(this.#activeConnections)) {
conn = this.#activeConnections[threadId];
if (!conn) {
break;
}
}
}
if (conn != null) {
if (conn) {
info = conn.info;

@@ -392,7 +421,7 @@ }

async _createConnection() {
const conn = new Connection(this.#opts.connOptions);
const conn = new Connection(this.opts.connOptions);
await conn.connect();
const pool = this;
conn.forceEnd = conn.end;
conn.release = function (resolve, release) {
conn.release = function (resolve, reject) {
if (pool.#closed || !conn.isValid()) {

@@ -403,3 +432,3 @@ pool._destroy(conn);

}
if (pool.#opts.noControlAfterUse) {
if (pool.opts.noControlAfterUse) {
pool.release(conn);

@@ -415,3 +444,3 @@ resolve();

if (
pool.#opts.resetAfterUse &&
pool.opts.resetAfterUse &&
conn.info.isMariaDB() &&

@@ -421,4 +450,4 @@ ((conn.info.serverVersion.minor === 2 && conn.info.hasMinVersion(10, 2, 22)) ||

) {
revertFunction = conn.reset.bind(conn);
} else revertFunction = conn.changeTransaction.bind(conn, 'ROLLBACK');
revertFunction = conn.reset.bind(conn, new CommandParameter());
} else revertFunction = conn.changeTransaction.bind(conn, new CommandParameter('ROLLBACK'));

@@ -431,2 +460,21 @@ new Promise(revertFunction).then(pool.release.bind(pool, conn), pool._destroy.bind(pool, conn)).finally(resolve);

_leakedConnections() {
let counter = 0;
for (const [key, value] of Object.entries(this.#activeConnections)) {
if (value.leaked) counter++;
}
return counter;
}
_errorMsgAddon() {
if (this.opts.leakDetectionTimeout > 0) {
return `\n (pool connections: active=${this.activeConnections()} idle=${this.idleConnections()} leak=${this._leakedConnections()} limit=${
this.opts.connectionLimit
})`;
}
return `\n (pool connections: active=${this.activeConnections()} idle=${this.idleConnections()} limit=${
this.opts.connectionLimit
})`;
}
//*****************************************************************

@@ -453,3 +501,7 @@ // public methods

activeConnections() {
return Object.keys(this.#activeConnections).length;
let counter = 0;
for (const [key, value] of Object.entries(this.#activeConnections)) {
if (value) counter++;
}
return counter;
}

@@ -474,7 +526,7 @@

escape(value) {
return Utils.escape(this.#opts.connOptions, this._searchInfo(), value);
return Utils.escape(this.opts.connOptions, this._searchInfo(), value);
}
escapeId(value) {
return Utils.escapeId(this.#opts.connOptions, this._searchInfo(), value);
return Utils.escapeId(this.opts.connOptions, this._searchInfo(), value);
}

@@ -490,10 +542,11 @@

* wait until acquireTimeout.
*
* @param cmdParam for stackTrace error
* @return {Promise}
*/
getConnection() {
getConnection(cmdParam) {
if (this.#closed) {
return Promise.reject(Errors.createError('pool is closed', Errors.ER_POOL_ALREADY_CLOSED));
return Promise.reject(
Errors.createError('pool is closed', Errors.ER_POOL_ALREADY_CLOSED, null, 'HY000', null, false, cmdParam.stack)
);
}
return this._doAcquire().then(

@@ -507,16 +560,24 @@ (conn) => {

if (this.#closed) {
throw Errors.createError('Cannot add request to pool, pool is closed', Errors.ER_POOL_ALREADY_CLOSED);
throw Errors.createError(
'Cannot add request to pool, pool is closed',
Errors.ER_POOL_ALREADY_CLOSED,
null,
'HY000',
null,
false,
cmdParam.stack
);
}
// no idle connection available
// create a new connection if limit is not reached
this.emit('validateSize');
setImmediate(this.emit.bind(this, 'validateSize'));
return new Promise(
function (resolver, rejecter) {
// stack request
setImmediate(this.emit.bind(this, 'enqueue'));
const request = new Request(Date.now() + this.opts.acquireTimeout, cmdParam.stack, resolver, rejecter);
this.#requests.push(request);
if (!this.#requestTimeoutId) {
this.#requestTimeoutId = setTimeout(this._requestTimeoutHandler.bind(this), this.#opts.acquireTimeout);
this.#requestTimeoutId = setTimeout(this._requestTimeoutHandler.bind(this), this.opts.acquireTimeout);
}
// stack request
setImmediate(this.emit.bind(this, 'enqueue'));
this.#requests.push(new Request(Date.now() + this.#opts.acquireTimeout, resolver, rejecter));
}.bind(this)

@@ -540,3 +601,4 @@ );

clearInterval(this._sizeHandlerTimeout);
const cmdParam = new CommandParameter();
if (this.opts.trace) Error.captureStackTrace(cmdParam);
//close unused connections

@@ -546,3 +608,3 @@ const idleConnectionsEndings = [];

while ((conn = this.#idleConnections.shift())) {
idleConnectionsEndings.push(new Promise(conn.forceEnd.bind(conn)));
idleConnectionsEndings.push(new Promise(conn.forceEnd.bind(conn, cmdParam)));
}

@@ -552,7 +614,13 @@

this.#requestTimeoutId = null;
//reject all waiting task
if (!this.#requests.isEmpty()) {
const err = Errors.createError('pool is ending, connection request aborted', Errors.ER_CLOSING_POOL);
const err = Errors.createError(
'pool is ending, connection request aborted',
Errors.ER_CLOSING_POOL,
null,
'HY000',
null,
false,
cmdParam.stack
);
let task;

@@ -569,4 +637,5 @@ while ((task = this.#requests.shift())) {

class Request {
constructor(timeout, resolver, rejecter) {
constructor(timeout, stack, resolver, rejecter) {
this.timeout = timeout;
this.stack = stack;
this.resolver = resolver;

@@ -573,0 +642,0 @@ this.rejecter = rejecter;

{
"name": "mariadb",
"version": "3.0.0",
"description": "fast mariadb/mysql connector.",
"version": "3.0.1",
"description": "fast mariadb or mysql connector.",
"main": "promise.js",

@@ -22,3 +22,3 @@ "types": "types/index.d.ts",

"coverage:report": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
"benchmark": "node ./benchmarks/benchmarks.js",
"benchmark": "node benchmarks/benchmarks-all.js",
"generate": "node ./tools/generate-mariadb.js"

@@ -62,4 +62,4 @@ },

"chai": "^4.3.4",
"chalk": "^4.1.2",
"codecov": "^3.8.2",
"chalk": "^4.1.2",
"dom-parser": "^0.1.6",

@@ -66,0 +66,0 @@ "error-stack-parser": "^2.0.6",

@@ -18,6 +18,3 @@ <p align="center">

version before 2.4 is compatible with Node.js 6+
version after 2.4 is compatible with Node.js 10+
## Documentation

@@ -36,3 +33,13 @@

Connector is production grade quality, with multiple features:
* superfast batching
* fast pool
* easy debugging, trace pointing to code line on error
* allows data streaming without high memory consumption
* pipelining
* metadata skipping (for MariaDB server only)
* ...
see some of those features:
### Insert Streaming

@@ -71,7 +78,8 @@

MariaDB provides benchmarks comparing the Connector with popular Node.js MySQL clients, including:
MariaDB provides benchmarks comparing the Connector with other Node.js MariaDB/MySQL clients, including:
* [`promise-mysql`](https://www.npmjs.com/package/promise-mysql) version 5.0.4 + [`mysql`](https://www.npmjs.com/package/mysql) version 2.18.1
* [`mysql2`](https://www.npmjs.com/package/mysql2) version 2.2.5
* [`promise-mysql`](https://www.npmjs.com/package/promise-mysql) version 5.2.0 + [`mysql`](https://www.npmjs.com/package/mysql) version 2.18.1
* [`mysql2`](https://www.npmjs.com/package/mysql2) version 2.3.3
See the [Benchmarks](./documentation/benchmarks.md) page for multiple results.

@@ -81,18 +89,18 @@ #### query

```
select * from mysql.user - mysql x 1,442 ops/sec ±0.38%
select * from mysql.user - mysql2 x 1,484 ops/sec ±0.60%
select * from mysql.user - mariadb x 1,595 ops/sec ±0.38%
select 20 * int, 20 * varchar(32)
mysql : 3,086 ops/s ± 0.6%
mysql2 : 2,799.6 ops/s ± 1.6% ( -9.3% )
mariadb : 4,710.8 ops/s ± 1% ( +52.7% )
```
![select 20 * int, 20 * varchar(32) benchmark results](https://quickchart.io/chart/render/zm-ef74089a-be91-49f1-b5a0-5b9ac5752435?data1=3086&data2=2800&data3=4711)
<img src="https://quickchart.io/chart/render/zm-e2bd7f00-c7ca-4412-84e5-5284055056b5?data1=1442&data2=1484&data3=1595&title=select%20one%20mysql.user%0A%20%5B%20sql%3A%20select%20*%20from%20mysql.user%20LIMIT%201%20%5D" width="500" height="160"/>
#### execute
```
select * from mysql.user using execute - mysql2 x 2,257 ops/sec ±0.84%
select * from mysql.user using execute - mariadb x 2,651 ops/sec ±0.59%
select 20 * int, 20 * varchar(32) using execute
mysql2 : 2,998 ops/s ± 1.3%
mariadb : 4,419.6 ops/s ± 1% ( +47.4% )
```
![select 20 * int, 20 * varchar(32) using execute benchmark results](https://quickchart.io/chart/render/zm-36b213f4-8efe-4943-8f94-82edf94fce83?data1=2998&data2=4420)
<img src="https://quickchart.io/chart?devicePixelRatio=1.0&h=140&w=520&c=%7B%22type%22%3A%22horizontalBar%22%2C%22data%22%3A%7B%22datasets%22%3A%5B%7B%22label%22%3A%22mysql2%202.2.5%22%2C%22backgroundColor%22%3A%22%234285f4%22%2C%22data%22%3A%5B2257%5D%7D%2C%7B%22label%22%3A%22mariadb%203.0.1%22%2C%22backgroundColor%22%3A%22%23ff9900%22%2C%22data%22%3A%5B2651%5D%7D%5D%7D%2C%22options%22%3A%7B%22plugins%22%3A%7B%22datalabels%22%3A%7B%22anchor%22%3A%22end%22%2C%22align%22%3A%22start%22%2C%22color%22%3A%22%23fff%22%2C%22font%22%3A%7B%22weight%22%3A%22bold%22%7D%7D%7D%2C%22elements%22%3A%7B%22rectangle%22%3A%7B%22borderWidth%22%3A0%7D%7D%2C%22responsive%22%3Atrue%2C%22legend%22%3A%7B%22position%22%3A%22right%22%7D%2C%22title%22%3A%7B%22display%22%3Atrue%2C%22text%22%3A%22select%20one%20mysql.user%20using%20execute%5Cn%20%5B%20sql%3A%20select%20*%20from%20mysql.user%20LIMIT%201%20%5D%22%7D%2C%22scales%22%3A%7B%22xAxes%22%3A%5B%7B%22display%22%3Atrue%2C%22scaleLabel%22%3A%7B%22display%22%3Atrue%2C%22labelString%22%3A%22operations%20per%20second%22%7D%2C%22ticks%22%3A%7B%22beginAtZero%22%3Atrue%7D%7D%5D%7D%7D%7D" width="500" height="140"/>
For more information, see the [Benchmarks](./documentation/benchmarks.md) page.

@@ -142,2 +150,2 @@ ## Quick Start

[codecov-image]:https://codecov.io/gh/mariadb-corporation/mariadb-connector-nodejs/branch/master/graph/badge.svg
[codecov-url]:https://codecov.io/gh/mariadb-corporation/mariadb-connector-nodejs
[codecov-url]:https://codecov.io/gh/mariadb-corporation/mariadb-connector-nodejs

@@ -214,3 +214,3 @@ /* eslint-disable @typescript-eslint/no-explicit-any */

/**
* The milliseconds before a timeout occurs during the initial connection to the MySQL server. (Default: 10 seconds)
* The milliseconds before a timeout occurs during the initial connection to the MySQL server. (Default: 1000)
*/

@@ -499,2 +499,7 @@ connectTimeout?: number;

/**
* connection collation
*/
collation: null;
/**
* Server capabilities

@@ -576,3 +581,3 @@ * see https://mariadb.com/kb/en/library/connection/#capabilities

*/
batch(sql: string | QueryOptions, values?: any): Promise<UpsertResult[]>;
batch(sql: string | QueryOptions, values?: any): Promise<UpsertResult> | Promise<UpsertResult[]>;

@@ -679,3 +684,3 @@ /**

*/
batch(sql: string | QueryOptions, values?: any): Promise<UpsertResult[]>;
batch(sql: string | QueryOptions, values?: any): Promise<UpsertResult> | Promise<UpsertResult[]>;

@@ -739,3 +744,3 @@ /**

query(sql: string | QueryOptions, values?: any): Promise<any>;
batch(sql: string | QueryOptions, values?: any): Promise<UpsertResult[]>;
batch(sql: string | QueryOptions, values?: any): Promise<UpsertResult> | Promise<UpsertResult[]>;
execute(sql: string | QueryOptions, values?: any): Promise<any>;

@@ -742,0 +747,0 @@ }

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