Update bot

Took 2 hours 17 minutes
This commit is contained in:
2021-03-15 09:32:14 +01:00
parent e76ad758b8
commit 6102599e5d
201 changed files with 26670 additions and 87 deletions

113
node_modules/mysql2/lib/auth_41.js generated vendored Normal file
View File

@ -0,0 +1,113 @@
'use strict';
/*
4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
SERVER: public_seed=create_random_string()
send(public_seed)
CLIENT: recv(public_seed)
hash_stage1=sha1("password")
hash_stage2=sha1(hash_stage1)
reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
// this three steps are done in scramble()
send(reply)
SERVER: recv(reply)
hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
candidate_hash2=sha1(hash_stage1)
check(candidate_hash2==hash_stage2)
server stores sha1(sha1(password)) ( hash_stag2)
*/
const crypto = require('crypto');
function sha1(msg, msg1, msg2) {
const hash = crypto.createHash('sha1');
hash.update(msg);
if (msg1) {
hash.update(msg1);
}
if (msg2) {
hash.update(msg2);
}
return hash.digest();
}
function xor(a, b) {
if (!Buffer.isBuffer(a)) {
a = Buffer.from(a, 'binary');
}
if (!Buffer.isBuffer(b)) {
b = Buffer.from(b, 'binary');
}
const result = Buffer.allocUnsafe(a.length);
for (let i = 0; i < a.length; i++) {
result[i] = a[i] ^ b[i];
}
return result;
}
exports.xor = xor;
function token(password, scramble1, scramble2) {
// TODO: use buffers (not sure why strings here)
if (!password) {
return Buffer.alloc(0);
}
const stage1 = sha1(password);
return exports.calculateTokenFromPasswordSha(stage1, scramble1, scramble2);
}
exports.calculateTokenFromPasswordSha = function(
passwordSha,
scramble1,
scramble2
) {
// we use AUTH 41 here, and we need only the bytes we just need.
const authPluginData1 = scramble1.slice(0, 8);
const authPluginData2 = scramble2.slice(0, 12);
const stage2 = sha1(passwordSha);
const stage3 = sha1(authPluginData1, authPluginData2, stage2);
return xor(stage3, passwordSha);
};
exports.calculateToken = token;
exports.verifyToken = function(publicSeed1, publicSeed2, token, doubleSha) {
const hashStage1 = xor(token, sha1(publicSeed1, publicSeed2, doubleSha));
const candidateHash2 = sha1(hashStage1);
return candidateHash2.compare(doubleSha) === 0;
};
exports.doubleSha1 = function(password) {
return sha1(sha1(password));
};
function xorRotating(a, seed) {
if (!Buffer.isBuffer(a)) {
a = Buffer.from(a, 'binary');
}
if (!Buffer.isBuffer(seed)) {
seed = Buffer.from(seed, 'binary');
}
const result = Buffer.allocUnsafe(a.length);
const seedLen = seed.length;
for (let i = 0; i < a.length; i++) {
result[i] = a[i] ^ seed[i % seedLen];
}
return result;
}
exports.xorRotating = xorRotating;

View File

@ -0,0 +1,103 @@
'use strict';
// https://mysqlserverteam.com/mysql-8-0-4-new-default-authentication-plugin-caching_sha2_password/
const PLUGIN_NAME = 'caching_sha2_password';
const crypto = require('crypto');
const { xor, xorRotating } = require('../auth_41');
const REQUEST_SERVER_KEY_PACKET = Buffer.from([2]);
const FAST_AUTH_SUCCESS_PACKET = Buffer.from([3]);
const PERFORM_FULL_AUTHENTICATION_PACKET = Buffer.from([4]);
const STATE_INITIAL = 0;
const STATE_TOKEN_SENT = 1;
const STATE_WAIT_SERVER_KEY = 2;
const STATE_FINAL = -1;
function sha256(msg) {
const hash = crypto.createHash('sha256');
hash.update(msg, 'binary');
return hash.digest('binary');
}
function calculateToken(password, scramble) {
if (!password) {
return Buffer.alloc(0);
}
const stage1 = sha256(Buffer.from(password, 'utf8').toString('binary'));
const stage2 = sha256(stage1);
const stage3 = sha256(stage2 + scramble.toString('binary'));
return xor(stage1, stage3);
}
function encrypt(password, scramble, key) {
const stage1 = xorRotating(
Buffer.from(`${password}\0`, 'utf8').toString('binary'),
scramble.toString('binary')
);
return crypto.publicEncrypt(key, stage1);
}
module.exports = (pluginOptions = {}) => ({ connection }) => {
let state = 0;
let scramble = null;
const password = connection.config.password;
const authWithKey = serverKey => {
const _password = encrypt(password, scramble, serverKey);
state = STATE_FINAL;
return _password;
};
return data => {
switch (state) {
case STATE_INITIAL:
scramble = data.slice(0, 20);
state = STATE_TOKEN_SENT;
return calculateToken(password, scramble);
case STATE_TOKEN_SENT:
if (FAST_AUTH_SUCCESS_PACKET.equals(data)) {
state = STATE_FINAL;
return null;
}
if (PERFORM_FULL_AUTHENTICATION_PACKET.equals(data)) {
const isSecureConnection =
typeof pluginOptions.overrideIsSecure === 'undefined'
? connection.config.ssl || connection.config.socketPath
: pluginOptions.overrideIsSecure;
if (isSecureConnection) {
state = STATE_FINAL;
return Buffer.from(`${password}\0`, 'utf8');
}
// if client provides key we can save one extra roundrip on first connection
if (pluginOptions.serverPublicKey) {
return authWithKey(pluginOptions.serverPublicKey);
}
state = STATE_WAIT_SERVER_KEY;
return REQUEST_SERVER_KEY_PACKET;
}
throw new Error(
`Invalid AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_TOKEN_SENT state.`
);
case STATE_WAIT_SERVER_KEY:
if (pluginOptions.onServerPublicKey) {
pluginOptions.onServerPublicKey(data);
}
return authWithKey(data);
case STATE_FINAL:
throw new Error(
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_FINAL state.`
);
}
throw new Error(
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in state ${state}`
);
};
};

View File

@ -0,0 +1,18 @@
##
https://mysqlserverteam.com/mysql-8-0-4-new-default-authentication-plugin-caching_sha2_password/
```js
const mysql = require('mysql');
mysql.createConnection({
authPlugins: {
caching_sha2_password: mysql.authPlugins.caching_sha2_password({
onServerPublikKey: function(key) {
console.log(key);
},
serverPublicKey: 'xxxyyy',
overrideIsSecure: true //
})
}
});
```

0
node_modules/mysql2/lib/auth_plugins/index.js generated vendored Normal file
View File

View File

@ -0,0 +1,32 @@
'use strict';
//const PLUGIN_NAME = 'mysql_native_password';
const auth41 = require('../auth_41.js');
module.exports = pluginOptions => ({ connection, command }) => {
const password =
command.password || pluginOptions.password || connection.config.password;
const passwordSha1 =
command.passwordSha1 ||
pluginOptions.passwordSha1 ||
connection.config.passwordSha1;
return data => {
const authPluginData1 = data.slice(0, 8);
const authPluginData2 = data.slice(8, 20);
let authToken;
if (passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
passwordSha1,
authPluginData1,
authPluginData2
);
} else {
authToken = auth41.calculateToken(
password,
authPluginData1,
authPluginData2
);
}
return authToken;
};
};

View File

@ -0,0 +1,60 @@
'use strict';
const PLUGIN_NAME = 'sha256_password';
const crypto = require('crypto');
const { xor } = require('../auth_41');
const REQUEST_SERVER_KEY_PACKET = Buffer.from([1]);
const STATE_INITIAL = 0;
const STATE_WAIT_SERVER_KEY = 1;
const STATE_FINAL = -1;
function encrypt(password, scramble, key) {
const stage1 = xor(
Buffer.from(`${password}\0`, 'utf8').toString('binary'),
scramble.toString('binary')
);
return crypto.publicEncrypt(key, stage1);
}
module.exports = (pluginOptions = {}) => ({ connection }) => {
let state = 0;
let scramble = null;
const password = connection.config.password;
const authWithKey = serverKey => {
const _password = encrypt(password, scramble, serverKey);
state = STATE_FINAL;
return _password;
};
return data => {
switch (state) {
case STATE_INITIAL:
scramble = data.slice(0, 20);
// if client provides key we can save one extra roundrip on first connection
if (pluginOptions.serverPublicKey) {
return authWithKey(pluginOptions.serverPublicKey);
}
state = STATE_WAIT_SERVER_KEY;
return REQUEST_SERVER_KEY_PACKET;
case STATE_WAIT_SERVER_KEY:
if (pluginOptions.onServerPublicKey) {
pluginOptions.onServerPublicKey(data);
}
return authWithKey(data);
case STATE_FINAL:
throw new Error(
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_FINAL state.`
);
}
throw new Error(
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in state ${state}`
);
};
};

91
node_modules/mysql2/lib/commands/auth_switch.js generated vendored Normal file
View File

@ -0,0 +1,91 @@
'use strict';
const Packets = require('../packets/index.js');
const sha256_password = require('../auth_plugins/sha256_password');
const caching_sha2_password = require('../auth_plugins/caching_sha2_password.js');
const mysql_native_password = require('../auth_plugins/mysql_native_password.js');
const standardAuthPlugins = {
sha256_password: sha256_password({}),
caching_sha2_password: caching_sha2_password({}),
mysql_native_password: mysql_native_password({})
};
function warnLegacyAuthSwitch() {
console.warn(
'WARNING! authSwitchHandler api is deprecated, please use new authPlugins api'
);
}
function authSwitchRequest(packet, connection, command) {
const { pluginName, pluginData } = Packets.AuthSwitchRequest.fromPacket(
packet
);
let authPlugin =
connection.config.authPlugins && connection.config.authPlugins[pluginName];
// legacy plugin api don't allow to override mysql_native_password
// if pluginName is mysql_native_password it's using standard auth4.1 auth
if (
connection.config.authSwitchHandler &&
pluginName !== 'mysql_native_password'
) {
const legacySwitchHandler = connection.config.authSwitchHandler;
warnLegacyAuthSwitch();
legacySwitchHandler({ pluginName, pluginData }, (err, data) => {
if (err) {
connection.emit('error', err);
return;
}
connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
});
return;
}
if (!authPlugin) {
authPlugin = standardAuthPlugins[pluginName];
}
if (!authPlugin) {
throw new Error(
`Server requests authentication using unknown plugin ${pluginName}. See ${'TODO: add plugins doco here'} on how to configure or author authentication plugins.`
);
}
connection._authPlugin = authPlugin({ connection, command });
Promise.resolve(connection._authPlugin(pluginData)).then(data => {
if (data) {
connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
}
});
}
function authSwitchRequestMoreData(packet, connection) {
const { data } = Packets.AuthSwitchRequestMoreData.fromPacket(packet);
if (connection.config.authSwitchHandler) {
const legacySwitchHandler = connection.config.authSwitchHandler;
warnLegacyAuthSwitch();
legacySwitchHandler({ pluginData: data }, (err, data) => {
if (err) {
connection.emit('error', err);
return;
}
connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
});
return;
}
if (!connection._authPlugin) {
throw new Error(
'AuthPluginMoreData received but no auth plugin instance found'
);
}
Promise.resolve(connection._authPlugin(data)).then(data => {
if (data) {
connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
}
});
}
module.exports = {
authSwitchRequest,
authSwitchRequestMoreData
};

109
node_modules/mysql2/lib/commands/binlog_dump.js generated vendored Normal file
View File

@ -0,0 +1,109 @@
'use strict';
const Command = require('./command');
const Packets = require('../packets');
const eventParsers = [];
class BinlogEventHeader {
constructor(packet) {
this.timestamp = packet.readInt32();
this.eventType = packet.readInt8();
this.serverId = packet.readInt32();
this.eventSize = packet.readInt32();
this.logPos = packet.readInt32();
this.flags = packet.readInt16();
}
}
class BinlogDump extends Command {
constructor(opts) {
super();
// this.onResult = callback;
this.opts = opts;
}
start(packet, connection) {
const newPacket = new Packets.BinlogDump(this.opts);
connection.writePacket(newPacket.toPacket(1));
return BinlogDump.prototype.binlogData;
}
binlogData(packet) {
// ok - continue consuming events
// error - error
// eof - end of binlog
if (packet.isEOF()) {
this.emit('eof');
return null;
}
// binlog event header
packet.readInt8();
const header = new BinlogEventHeader(packet);
const EventParser = eventParsers[header.eventType];
let event;
if (EventParser) {
event = new EventParser(packet);
} else {
event = {
name: 'UNKNOWN'
};
}
event.header = header;
this.emit('event', event);
return BinlogDump.prototype.binlogData;
}
}
class RotateEvent {
constructor(packet) {
this.pposition = packet.readInt32();
// TODO: read uint64 here
packet.readInt32(); // positionDword2
this.nextBinlog = packet.readString();
this.name = 'RotateEvent';
}
}
class FormatDescriptionEvent {
constructor(packet) {
this.binlogVersion = packet.readInt16();
this.serverVersion = packet.readString(50).replace(/\u0000.*/, ''); // eslint-disable-line no-control-regex
this.createTimestamp = packet.readInt32();
this.eventHeaderLength = packet.readInt8(); // should be 19
this.eventsLength = packet.readBuffer();
this.name = 'FormatDescriptionEvent';
}
}
class QueryEvent {
constructor(packet) {
const parseStatusVars = require('../packets/binlog_query_statusvars.js');
this.slaveProxyId = packet.readInt32();
this.executionTime = packet.readInt32();
const schemaLength = packet.readInt8();
this.errorCode = packet.readInt16();
const statusVarsLength = packet.readInt16();
const statusVars = packet.readBuffer(statusVarsLength);
this.schema = packet.readString(schemaLength);
packet.readInt8(); // should be zero
this.statusVars = parseStatusVars(statusVars);
this.query = packet.readString();
this.name = 'QueryEvent';
}
}
class XidEvent {
constructor(packet) {
this.binlogVersion = packet.readInt16();
this.xid = packet.readInt64();
this.name = 'XidEvent';
}
}
eventParsers[2] = QueryEvent;
eventParsers[4] = RotateEvent;
eventParsers[15] = FormatDescriptionEvent;
eventParsers[16] = XidEvent;
module.exports = BinlogDump;

47
node_modules/mysql2/lib/commands/change_user.js generated vendored Normal file
View File

@ -0,0 +1,47 @@
'use strict';
const Command = require('./command.js');
const Packets = require('../packets/index.js');
const ClientHandshake = require('./client_handshake.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
class ChangeUser extends Command {
constructor(options, callback) {
super();
this.onResult = callback;
this.user = options.user;
this.password = options.password;
this.database = options.database;
this.passwordSha1 = options.passwordSha1;
this.charsetNumber = options.charsetNumber;
this.currentConfig = options.currentConfig;
}
start(packet, connection) {
const newPacket = new Packets.ChangeUser({
flags: connection.config.clientFlags,
user: this.user,
database: this.database,
charsetNumber: this.charsetNumber,
password: this.password,
passwordSha1: this.passwordSha1,
authPluginData1: connection._handshakePacket.authPluginData1,
authPluginData2: connection._handshakePacket.authPluginData2
});
this.currentConfig.user = this.user;
this.currentConfig.password = this.password;
this.currentConfig.database = this.database;
this.currentConfig.charsetNumber = this.charsetNumber;
connection.clientEncoding = CharsetToEncoding[this.charsetNumber];
// reset prepared statements cache as all statements become invalid after changeUser
connection._statements.reset();
connection.writePacket(newPacket.toPacket());
return ChangeUser.prototype.handshakeResult;
}
}
ChangeUser.prototype.handshakeResult =
ClientHandshake.prototype.handshakeResult;
ChangeUser.prototype.calculateNativePasswordAuthToken =
ClientHandshake.prototype.calculateNativePasswordAuthToken;
module.exports = ChangeUser;

187
node_modules/mysql2/lib/commands/client_handshake.js generated vendored Normal file
View File

@ -0,0 +1,187 @@
'use strict';
const Command = require('./command.js');
const Packets = require('../packets/index.js');
const ClientConstants = require('../constants/client.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const auth41 = require('../auth_41.js');
function flagNames(flags) {
const res = [];
for (const c in ClientConstants) {
if (flags & ClientConstants[c]) {
res.push(c.replace(/_/g, ' ').toLowerCase());
}
}
return res;
}
class ClientHandshake extends Command {
constructor(clientFlags) {
super();
this.handshake = null;
this.clientFlags = clientFlags;
}
start() {
return ClientHandshake.prototype.handshakeInit;
}
sendSSLRequest(connection) {
const sslRequest = new Packets.SSLRequest(
this.clientFlags,
connection.config.charsetNumber
);
connection.writePacket(sslRequest.toPacket());
}
sendCredentials(connection) {
if (connection.config.debug) {
// eslint-disable-next-line
console.log(
'Sending handshake packet: flags:%d=(%s)',
this.clientFlags,
flagNames(this.clientFlags).join(', ')
);
}
this.user = connection.config.user;
this.password = connection.config.password;
this.passwordSha1 = connection.config.passwordSha1;
this.database = connection.config.database;
this.autPluginName = this.handshake.autPluginName;
const handshakeResponse = new Packets.HandshakeResponse({
flags: this.clientFlags,
user: this.user,
database: this.database,
password: this.password,
passwordSha1: this.passwordSha1,
charsetNumber: connection.config.charsetNumber,
authPluginData1: this.handshake.authPluginData1,
authPluginData2: this.handshake.authPluginData2,
compress: connection.config.compress,
connectAttributes: connection.config.connectAttributes
});
connection.writePacket(handshakeResponse.toPacket());
}
calculateNativePasswordAuthToken(authPluginData) {
// TODO: dont split into authPluginData1 and authPluginData2, instead join when 1 & 2 received
const authPluginData1 = authPluginData.slice(0, 8);
const authPluginData2 = authPluginData.slice(8, 20);
let authToken;
if (this.passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
this.passwordSha1,
authPluginData1,
authPluginData2
);
} else {
authToken = auth41.calculateToken(
this.password,
authPluginData1,
authPluginData2
);
}
return authToken;
}
handshakeInit(helloPacket, connection) {
this.on('error', e => {
connection._fatalError = e;
connection._protocolError = e;
});
this.handshake = Packets.Handshake.fromPacket(helloPacket);
if (connection.config.debug) {
// eslint-disable-next-line
console.log(
'Server hello packet: capability flags:%d=(%s)',
this.handshake.capabilityFlags,
flagNames(this.handshake.capabilityFlags).join(', ')
);
}
connection.serverCapabilityFlags = this.handshake.capabilityFlags;
connection.serverEncoding = CharsetToEncoding[this.handshake.characterSet];
connection.connectionId = this.handshake.connectionId;
const serverSSLSupport =
this.handshake.capabilityFlags & ClientConstants.SSL;
// use compression only if requested by client and supported by server
connection.config.compress =
connection.config.compress &&
this.handshake.capabilityFlags & ClientConstants.COMPRESS;
this.clientFlags = this.clientFlags | connection.config.compress;
if (connection.config.ssl) {
// client requires SSL but server does not support it
if (!serverSSLSupport) {
const err = new Error('Server does not support secure connnection');
err.code = 'HANDSHAKE_NO_SSL_SUPPORT';
err.fatal = true;
this.emit('error', err);
return false;
}
// send ssl upgrade request and immediately upgrade connection to secure
this.clientFlags |= ClientConstants.SSL;
this.sendSSLRequest(connection);
connection.startTLS(err => {
// after connection is secure
if (err) {
// SSL negotiation error are fatal
err.code = 'HANDSHAKE_SSL_ERROR';
err.fatal = true;
this.emit('error', err);
return;
}
// rest of communication is encrypted
this.sendCredentials(connection);
});
} else {
this.sendCredentials(connection);
}
return ClientHandshake.prototype.handshakeResult;
}
handshakeResult(packet, connection) {
const marker = packet.peekByte();
if (marker === 0xfe || marker === 1) {
const authSwitch = require('./auth_switch');
try {
if (marker === 1) {
authSwitch.authSwitchRequestMoreData(packet, connection, this);
} else {
authSwitch.authSwitchRequest(packet, connection, this);
}
return ClientHandshake.prototype.handshakeResult;
} catch (err) {
if (this.onResult) {
this.onResult(err);
} else {
connection.emit('error', err);
}
return null;
}
}
if (marker !== 0) {
const err = new Error('Unexpected packet during handshake phase');
if (this.onResult) {
this.onResult(err);
} else {
connection.emit('error', err);
}
return null;
}
// this should be called from ClientHandshake command only
// and skipped when called from ChangeUser command
if (!connection.authorized) {
connection.authorized = true;
if (connection.config.compress) {
const enableCompression = require('../compressed_protocol.js')
.enableCompression;
enableCompression(connection);
}
}
if (this.onResult) {
this.onResult(null);
}
return null;
}
}
module.exports = ClientHandshake;

18
node_modules/mysql2/lib/commands/close_statement.js generated vendored Normal file
View File

@ -0,0 +1,18 @@
'use strict';
const Command = require('./command');
const Packets = require('../packets/index.js');
class CloseStatement extends Command {
constructor(id) {
super();
this.id = id;
}
start(packet, connection) {
connection.writePacket(new Packets.CloseStatement(this.id).toPacket(1));
return null;
}
}
module.exports = CloseStatement;

49
node_modules/mysql2/lib/commands/command.js generated vendored Normal file
View File

@ -0,0 +1,49 @@
'use strict';
const EventEmitter = require('events').EventEmitter;
class Command extends EventEmitter {
constructor() {
super();
this.next = null;
}
// slow. debug only
stateName() {
const state = this.next;
for (const i in this) {
if (this[i] === state && i !== 'next') {
return i;
}
}
return 'unknown name';
}
execute(packet, connection) {
if (!this.next) {
this.next = this.start;
connection._resetSequenceId();
}
if (packet && packet.isError()) {
const err = packet.asError(connection.clientEncoding);
if (this.onResult) {
this.onResult(err);
this.emit('end');
} else {
this.emit('error', err);
this.emit('end');
}
return true;
}
// TODO: don't return anything from execute, it's ugly and error-prone. Listen for 'end' event in connection
this.next = this.next(packet, connection);
if (this.next) {
return false;
}
this.emit('end');
return true;
}
}
module.exports = Command;

102
node_modules/mysql2/lib/commands/execute.js generated vendored Normal file
View File

@ -0,0 +1,102 @@
'use strict';
const Command = require('./command.js');
const Query = require('./query.js');
const Packets = require('../packets/index.js');
const getBinaryParser = require('../parsers/binary_parser.js');
class Execute extends Command {
constructor(options, callback) {
super();
this.statement = options.statement;
this.sql = options.sql;
this.values = options.values;
this.onResult = callback;
this.parameters = options.values;
this.insertId = 0;
this._rows = [];
this._fields = [];
this._result = [];
this._fieldCount = 0;
this._rowParser = null;
this._executeOptions = options;
this._resultIndex = 0;
this._localStream = null;
this._unpipeStream = function() {};
this._streamFactory = options.infileStreamFactory;
this._connection = null;
}
buildParserFromFields(fields, connection) {
return getBinaryParser(fields, this.options, connection.config);
}
start(packet, connection) {
this._connection = connection;
this.options = Object.assign({}, connection.config, this._executeOptions);
const executePacket = new Packets.Execute(
this.statement.id,
this.parameters,
connection.config.charsetNumber,
connection.config.timezone
);
//For reasons why this try-catch is here, please see
// https://github.com/sidorares/node-mysql2/pull/689
//For additional discussion, see
// 1. https://github.com/sidorares/node-mysql2/issues/493
// 2. https://github.com/sidorares/node-mysql2/issues/187
// 3. https://github.com/sidorares/node-mysql2/issues/480
try {
connection.writePacket(executePacket.toPacket(1));
} catch (error) {
this.onResult(error);
}
return Execute.prototype.resultsetHeader;
}
readField(packet, connection) {
let fields;
// disabling for now, but would be great to find reliable way to parse fields only once
// fields reported by prepare can be empty at all or just incorrect - see #169
//
// perfomance optimisation: if we already have this field parsed in statement header, use one from header
// const field = this.statement.columns.length == this._fieldCount ?
// this.statement.columns[this._receivedFieldsCount] : new Packets.ColumnDefinition(packet);
const field = new Packets.ColumnDefinition(
packet,
connection.clientEncoding
);
this._receivedFieldsCount++;
this._fields[this._resultIndex].push(field);
if (this._receivedFieldsCount === this._fieldCount) {
fields = this._fields[this._resultIndex];
this.emit('fields', fields, this._resultIndex);
return Execute.prototype.fieldsEOF;
}
return Execute.prototype.readField;
}
fieldsEOF(packet, connection) {
// check EOF
if (!packet.isEOF()) {
return connection.protocolError('Expected EOF packet');
}
this._rowParser = this.buildParserFromFields(
this._fields[this._resultIndex],
connection
);
return Execute.prototype.row;
}
}
Execute.prototype.done = Query.prototype.done;
Execute.prototype.doneInsert = Query.prototype.doneInsert;
Execute.prototype.resultsetHeader = Query.prototype.resultsetHeader;
Execute.prototype._findOrCreateReadStream =
Query.prototype._findOrCreateReadStream;
Execute.prototype._streamLocalInfile = Query.prototype._streamLocalInfile;
Execute.prototype.row = Query.prototype.row;
Execute.prototype.stream = Query.prototype.stream;
module.exports = Execute;

27
node_modules/mysql2/lib/commands/index.js generated vendored Normal file
View File

@ -0,0 +1,27 @@
'use strict';
const ClientHandshake = require('./client_handshake.js');
const ServerHandshake = require('./server_handshake.js');
const Query = require('./query.js');
const Prepare = require('./prepare.js');
const CloseStatement = require('./close_statement.js');
const Execute = require('./execute.js');
const Ping = require('./ping.js');
const RegisterSlave = require('./register_slave.js');
const BinlogDump = require('./binlog_dump.js');
const ChangeUser = require('./change_user.js');
const Quit = require('./quit.js');
module.exports = {
ClientHandshake,
ServerHandshake,
Query,
Prepare,
CloseStatement,
Execute,
Ping,
RegisterSlave,
BinlogDump,
ChangeUser,
Quit
};

36
node_modules/mysql2/lib/commands/ping.js generated vendored Normal file
View File

@ -0,0 +1,36 @@
'use strict';
const Command = require('./command');
const CommandCode = require('../constants/commands');
const Packet = require('../packets/packet');
// TODO: time statistics?
// usefull for queue size and network latency monitoring
// store created,sent,reply timestamps
class Ping extends Command {
constructor(callback) {
super();
this.onResult = callback;
}
start(packet, connection) {
const ping = new Packet(
0,
Buffer.from([1, 0, 0, 0, CommandCode.PING]),
0,
5
);
connection.writePacket(ping);
return Ping.prototype.pingResponse;
}
pingResponse() {
// TODO: check it's OK packet. error check already done in caller
if (this.onResult) {
process.nextTick(this.onResult.bind(this));
}
return null;
}
}
module.exports = Ping;

130
node_modules/mysql2/lib/commands/prepare.js generated vendored Normal file
View File

@ -0,0 +1,130 @@
'use strict';
const Packets = require('../packets/index.js');
const Command = require('./command.js');
const CloseStatement = require('./close_statement.js');
const Execute = require('./execute.js');
class PreparedStatementInfo {
constructor(query, id, columns, parameters, connection) {
this.query = query;
this.id = id;
this.columns = columns;
this.parameters = parameters;
this.rowParser = null;
this._connection = connection;
}
close() {
return this._connection.addCommand(new CloseStatement(this.id));
}
execute(parameters, callback) {
if (typeof parameters === 'function') {
callback = parameters;
parameters = [];
}
return this._connection.addCommand(
new Execute({ statement: this, values: parameters }, callback)
);
}
}
class Prepare extends Command {
constructor(options, callback) {
super();
this.query = options.sql;
this.onResult = callback;
this.id = 0;
this.fieldCount = 0;
this.parameterCount = 0;
this.fields = [];
this.parameterDefinitions = [];
this.options = options;
}
start(packet, connection) {
const Connection = connection.constructor;
this.key = Connection.statementKey(this.options);
const statement = connection._statements.get(this.key);
if (statement) {
if (this.onResult) {
this.onResult(null, statement);
}
return null;
}
const cmdPacket = new Packets.PrepareStatement(
this.query,
connection.config.charsetNumber
);
connection.writePacket(cmdPacket.toPacket(1));
return Prepare.prototype.prepareHeader;
}
prepareHeader(packet, connection) {
const header = new Packets.PreparedStatementHeader(packet);
this.id = header.id;
this.fieldCount = header.fieldCount;
this.parameterCount = header.parameterCount;
if (this.parameterCount > 0) {
return Prepare.prototype.readParameter;
} if (this.fieldCount > 0) {
return Prepare.prototype.readField;
}
return this.prepareDone(connection);
}
readParameter(packet, connection) {
const def = new Packets.ColumnDefinition(packet, connection.clientEncoding);
this.parameterDefinitions.push(def);
if (this.parameterDefinitions.length === this.parameterCount) {
return Prepare.prototype.parametersEOF;
}
return this.readParameter;
}
readField(packet, connection) {
const def = new Packets.ColumnDefinition(packet, connection.clientEncoding);
this.fields.push(def);
if (this.fields.length === this.fieldCount) {
return Prepare.prototype.fieldsEOF;
}
return Prepare.prototype.readField;
}
parametersEOF(packet, connection) {
if (!packet.isEOF()) {
return connection.protocolError('Expected EOF packet after parameters');
}
if (this.fieldCount > 0) {
return Prepare.prototype.readField;
}
return this.prepareDone(connection);
}
fieldsEOF(packet, connection) {
if (!packet.isEOF()) {
return connection.protocolError('Expected EOF packet after fields');
}
return this.prepareDone(connection);
}
prepareDone(connection) {
const statement = new PreparedStatementInfo(
this.query,
this.id,
this.fields,
this.parameterDefinitions,
connection
);
connection._statements.set(this.key, statement);
if (this.onResult) {
this.onResult(null, statement);
}
return null;
}
}
module.exports = Prepare;

279
node_modules/mysql2/lib/commands/query.js generated vendored Normal file
View File

@ -0,0 +1,279 @@
'use strict';
const process = require('process');
const Readable = require('stream').Readable;
const Command = require('./command.js');
const Packets = require('../packets/index.js');
const getTextParser = require('../parsers/text_parser.js');
const ServerStatus = require('../constants/server_status.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const EmptyPacket = new Packets.Packet(0, Buffer.allocUnsafe(4), 0, 4);
// http://dev.mysql.com/doc/internals/en/com-query.html
class Query extends Command {
constructor(options, callback) {
super();
this.sql = options.sql;
this.values = options.values;
this._queryOptions = options;
this.namedPlaceholders = options.namedPlaceholders || false;
this.onResult = callback;
this._fieldCount = 0;
this._rowParser = null;
this._fields = [];
this._rows = [];
this._receivedFieldsCount = 0;
this._resultIndex = 0;
this._localStream = null;
this._unpipeStream = function() {};
this._streamFactory = options.infileStreamFactory;
this._connection = null;
}
then() {
const err =
"You have tried to call .then(), .catch(), or invoked await on the result of query that is not a promise, which is a programming error. Try calling con.promise().query(), or require('mysql2/promise') instead of 'mysql2' for a promise-compatible version of the query interface. To learn how to use async/await or Promises check out documentation at https://www.npmjs.com/package/mysql2#using-promise-wrapper, or the mysql2 documentation at https://github.com/sidorares/node-mysql2/tree/master/documentation/Promise-Wrapper.md";
// eslint-disable-next-line
console.log(err);
throw new Error(err);
}
start(packet, connection) {
if (connection.config.debug) {
// eslint-disable-next-line
console.log(' Sending query command: %s', this.sql);
}
this._connection = connection;
this.options = Object.assign({}, connection.config, this._queryOptions);
const cmdPacket = new Packets.Query(
this.sql,
connection.config.charsetNumber
);
connection.writePacket(cmdPacket.toPacket(1));
return Query.prototype.resultsetHeader;
}
done() {
this._unpipeStream();
if (this.onResult) {
let rows, fields;
if (this._resultIndex === 0) {
rows = this._rows[0];
fields = this._fields[0];
} else {
rows = this._rows;
fields = this._fields;
}
if (fields) {
process.nextTick(() => {
this.onResult(null, rows, fields);
});
} else {
process.nextTick(() => {
this.onResult(null, rows);
});
}
}
return null;
}
doneInsert(rs) {
if (this._localStreamError) {
if (this.onResult) {
this.onResult(this._localStreamError, rs);
} else {
this.emit('error', this._localStreamError);
}
return null;
}
this._rows.push(rs);
this._fields.push(void 0);
this.emit('fields', void 0);
this.emit('result', rs);
if (rs.serverStatus & ServerStatus.SERVER_MORE_RESULTS_EXISTS) {
this._resultIndex++;
return this.resultsetHeader;
}
return this.done();
}
resultsetHeader(packet, connection) {
const rs = new Packets.ResultSetHeader(packet, connection);
this._fieldCount = rs.fieldCount;
if (connection.config.debug) {
// eslint-disable-next-line
console.log(
` Resultset header received, expecting ${rs.fieldCount} column definition packets`
);
}
if (this._fieldCount === 0) {
return this.doneInsert(rs);
}
if (this._fieldCount === null) {
return this._streamLocalInfile(connection, rs.infileName);
}
this._receivedFieldsCount = 0;
this._rows.push([]);
this._fields.push([]);
return this.readField;
}
_streamLocalInfile(connection, path) {
if (this._streamFactory) {
this._localStream = this._streamFactory(path);
} else {
this._localStreamError = new Error(
`As a result of LOCAL INFILE command server wants to read ${path} file, but as of v2.0 you must provide streamFactory option returning ReadStream.`
);
connection.writePacket(EmptyPacket);
return this.infileOk;
}
const onConnectionError = () => {
this._unpipeStream();
};
const onDrain = () => {
this._localStream.resume();
};
const onPause = () => {
this._localStream.pause();
};
const onData = function(data) {
const dataWithHeader = Buffer.allocUnsafe(data.length + 4);
data.copy(dataWithHeader, 4);
connection.writePacket(
new Packets.Packet(0, dataWithHeader, 0, dataWithHeader.length)
);
};
const onEnd = () => {
connection.removeListener('error', onConnectionError);
connection.writePacket(EmptyPacket);
};
const onError = err => {
this._localStreamError = err;
connection.removeListener('error', onConnectionError);
connection.writePacket(EmptyPacket);
};
this._unpipeStream = () => {
connection.stream.removeListener('pause', onPause);
connection.stream.removeListener('drain', onDrain);
this._localStream.removeListener('data', onData);
this._localStream.removeListener('end', onEnd);
this._localStream.removeListener('error', onError);
};
connection.stream.on('pause', onPause);
connection.stream.on('drain', onDrain);
this._localStream.on('data', onData);
this._localStream.on('end', onEnd);
this._localStream.on('error', onError);
connection.once('error', onConnectionError);
return this.infileOk;
}
readField(packet, connection) {
this._receivedFieldsCount++;
// Often there is much more data in the column definition than in the row itself
// If you set manually _fields[0] to array of ColumnDefinition's (from previous call)
// you can 'cache' result of parsing. Field packets still received, but ignored in that case
// this is the reason _receivedFieldsCount exist (otherwise we could just use current length of fields array)
if (this._fields[this._resultIndex].length !== this._fieldCount) {
const field = new Packets.ColumnDefinition(
packet,
connection.clientEncoding
);
this._fields[this._resultIndex].push(field);
if (connection.config.debug) {
/* eslint-disable no-console */
console.log(' Column definition:');
console.log(` name: ${field.name}`);
console.log(` type: ${field.columnType}`);
console.log(` flags: ${field.flags}`);
/* eslint-enable no-console */
}
}
// last field received
if (this._receivedFieldsCount === this._fieldCount) {
const fields = this._fields[this._resultIndex];
this.emit('fields', fields);
this._rowParser = getTextParser(fields, this.options, connection.config);
return Query.prototype.fieldsEOF;
}
return Query.prototype.readField;
}
fieldsEOF(packet, connection) {
// check EOF
if (!packet.isEOF()) {
return connection.protocolError('Expected EOF packet');
}
return this.row;
}
row(packet) {
if (packet.isEOF()) {
const status = packet.eofStatusFlags();
const moreResults = status & ServerStatus.SERVER_MORE_RESULTS_EXISTS;
if (moreResults) {
this._resultIndex++;
return Query.prototype.resultsetHeader;
}
return this.done();
}
let row;
try {
row = new this._rowParser(
packet,
this._fields[this._resultIndex],
this.options,
CharsetToEncoding
);
} catch (err) {
this._localStreamError = err;
return this.doneInsert(null);
}
if (this.onResult) {
this._rows[this._resultIndex].push(row);
} else {
this.emit('result', row);
}
return Query.prototype.row;
}
infileOk(packet, connection) {
const rs = new Packets.ResultSetHeader(packet, connection);
return this.doneInsert(rs);
}
stream(options) {
options = options || {};
options.objectMode = true;
const stream = new Readable(options);
stream._read = () => {
this._connection && this._connection.resume();
};
this.on('result', row => {
if (!stream.push(row)) {
this._connection.pause();
}
stream.emit('result', row); // replicate old emitter
});
this.on('error', err => {
stream.emit('error', err); // Pass on any errors
});
this.on('end', () => {
stream.push(null); // pushing null, indicating EOF
stream.emit('close'); // notify readers that query has completed
});
this.on('fields', fields => {
stream.emit('fields', fields); // replicate old emitter
});
return stream;
}
}
Query.prototype.catch = Query.prototype.then;
module.exports = Query;

29
node_modules/mysql2/lib/commands/quit.js generated vendored Normal file
View File

@ -0,0 +1,29 @@
'use strict';
const Command = require('./command.js');
const CommandCode = require('../constants/commands.js');
const Packet = require('../packets/packet.js');
class Quit extends Command {
constructor(callback) {
super();
this.done = callback;
}
start(packet, connection) {
connection._closing = true;
const quit = new Packet(
0,
Buffer.from([1, 0, 0, 0, CommandCode.QUIT]),
0,
5
);
if (this.done) {
this.done();
}
connection.writePacket(quit);
return null;
}
}
module.exports = Quit;

27
node_modules/mysql2/lib/commands/register_slave.js generated vendored Normal file
View File

@ -0,0 +1,27 @@
'use strict';
const Command = require('./command');
const Packets = require('../packets');
class RegisterSlave extends Command {
constructor(opts, callback) {
super();
this.onResult = callback;
this.opts = opts;
}
start(packet, connection) {
const newPacket = new Packets.RegisterSlave(this.opts);
connection.writePacket(newPacket.toPacket(1));
return RegisterSlave.prototype.registerResponse;
}
registerResponse() {
if (this.onResult) {
process.nextTick(this.onResult.bind(this));
}
return null;
}
}
module.exports = RegisterSlave;

162
node_modules/mysql2/lib/commands/server_handshake.js generated vendored Normal file
View File

@ -0,0 +1,162 @@
'use strict';
const CommandCode = require('../constants/commands.js');
const Errors = require('../constants/errors.js');
const Command = require('./command.js');
const Packets = require('../packets/index.js');
class ServerHandshake extends Command {
constructor(args) {
super();
this.args = args;
/*
this.protocolVersion = args.protocolVersion || 10;
this.serverVersion = args.serverVersion;
this.connectionId = args.connectionId,
this.statusFlags = args.statusFlags,
this.characterSet = args.characterSet,
this.capabilityFlags = args.capabilityFlags || 512;
*/
}
start(packet, connection) {
const serverHelloPacket = new Packets.Handshake(this.args);
this.serverHello = serverHelloPacket;
serverHelloPacket.setScrambleData(err => {
if (err) {
connection.emit('error', new Error('Error generating random bytes'));
return;
}
connection.writePacket(serverHelloPacket.toPacket(0));
});
return ServerHandshake.prototype.readClientReply;
}
readClientReply(packet, connection) {
// check auth here
const clientHelloReply = Packets.HandshakeResponse.fromPacket(packet);
// TODO check we don't have something similar already
connection.clientHelloReply = clientHelloReply;
if (this.args.authCallback) {
this.args.authCallback(
{
user: clientHelloReply.user,
database: clientHelloReply.database,
address: connection.stream.remoteAddress,
authPluginData1: this.serverHello.authPluginData1,
authPluginData2: this.serverHello.authPluginData2,
authToken: clientHelloReply.authToken
},
(err, mysqlError) => {
// if (err)
if (!mysqlError) {
connection.writeOk();
} else {
// TODO create constants / errorToCode
// 1045 = ER_ACCESS_DENIED_ERROR
connection.writeError({
message: mysqlError.message || '',
code: mysqlError.code || 1045
});
connection.close();
}
}
);
} else {
connection.writeOk();
}
return ServerHandshake.prototype.dispatchCommands;
}
dispatchCommands(packet, connection) {
// command from client to server
let knownCommand = true;
const encoding = connection.clientHelloReply.encoding;
const commandCode = packet.readInt8();
switch (commandCode) {
case CommandCode.QUIT:
if (connection.listeners('quit').length) {
connection.emit('quit');
} else {
connection.stream.end();
}
break;
case CommandCode.INIT_DB:
if (connection.listeners('init_db').length) {
const schemaName = packet.readString(undefined, encoding);
connection.emit('init_db', schemaName);
} else {
connection.writeOk();
}
break;
case CommandCode.QUERY:
if (connection.listeners('query').length) {
const query = packet.readString(undefined, encoding);
connection.emit('query', query);
} else {
connection.writeError({
code: Errors.HA_ERR_INTERNAL_ERROR,
message: 'No query handler'
});
}
break;
case CommandCode.FIELD_LIST:
if (connection.listeners('field_list').length) {
const table = packet.readNullTerminatedString();
const fields = packet.readString(undefined, encoding);
connection.emit('field_list', table, fields);
} else {
connection.writeError({
code: Errors.ER_WARN_DEPRECATED_SYNTAX,
message:
'As of MySQL 5.7.11, COM_FIELD_LIST is deprecated and will be removed in a future version of MySQL.'
});
}
break;
case CommandCode.PING:
if (connection.listeners('ping').length) {
connection.emit('ping');
} else {
connection.writeOk();
}
break;
default:
knownCommand = false;
}
if (connection.listeners('packet').length) {
connection.emit('packet', packet.clone(), knownCommand, commandCode);
} else if (!knownCommand) {
// eslint-disable-next-line no-console
console.log('Unknown command:', commandCode);
}
return ServerHandshake.prototype.dispatchCommands;
}
}
module.exports = ServerHandshake;
// TODO: implement server-side 4.1 authentication
/*
4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
SERVER: public_seed=create_random_string()
send(public_seed)
CLIENT: recv(public_seed)
hash_stage1=sha1("password")
hash_stage2=sha1(hash_stage1)
reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
// this three steps are done in scramble()
send(reply)
SERVER: recv(reply)
hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
candidate_hash2=sha1(hash_stage1)
check(candidate_hash2==hash_stage2)
server stores sha1(sha1(password)) ( hash_stag2)
*/

127
node_modules/mysql2/lib/compressed_protocol.js generated vendored Normal file
View File

@ -0,0 +1,127 @@
'use strict';
// connection mixins
// implementation of http://dev.mysql.com/doc/internals/en/compression.html
const zlib = require('zlib');
const PacketParser = require('./packet_parser.js');
function handleCompressedPacket(packet) {
// eslint-disable-next-line consistent-this, no-invalid-this
const connection = this;
const deflatedLength = packet.readInt24();
const body = packet.readBuffer();
if (deflatedLength !== 0) {
connection.inflateQueue.push(task => {
zlib.inflate(body, (err, data) => {
if (err) {
connection._handleNetworkError(err);
return;
}
connection._bumpCompressedSequenceId(packet.numPackets);
connection._inflatedPacketsParser.execute(data);
task.done();
});
});
} else {
connection.inflateQueue.push(task => {
connection._bumpCompressedSequenceId(packet.numPackets);
connection._inflatedPacketsParser.execute(body);
task.done();
});
}
}
function writeCompressed(buffer) {
// http://dev.mysql.com/doc/internals/en/example-several-mysql-packets.html
// note: sending a MySQL Packet of the size 2^245 to 2^241 via compression
// leads to at least one extra compressed packet.
// (this is because "length of the packet before compression" need to fit
// into 3 byte unsigned int. "length of the packet before compression" includes
// 4 byte packet header, hence 2^245)
const MAX_COMPRESSED_LENGTH = 16777210;
let start;
if (buffer.length > MAX_COMPRESSED_LENGTH) {
for (start = 0; start < buffer.length; start += MAX_COMPRESSED_LENGTH) {
writeCompressed.call(
// eslint-disable-next-line no-invalid-this
this,
buffer.slice(start, start + MAX_COMPRESSED_LENGTH)
);
}
return;
}
// eslint-disable-next-line no-invalid-this, consistent-this
const connection = this;
let packetLen = buffer.length;
const compressHeader = Buffer.allocUnsafe(7);
// seqqueue is used here because zlib async execution is routed via thread pool
// internally and when we have multiple compressed packets arriving we need
// to assemble uncompressed result sequentially
(function(seqId) {
connection.deflateQueue.push(task => {
zlib.deflate(buffer, (err, compressed) => {
if (err) {
connection._handleFatalError(err);
return;
}
let compressedLength = compressed.length;
if (compressedLength < packetLen) {
compressHeader.writeUInt8(compressedLength & 0xff, 0);
compressHeader.writeUInt16LE(compressedLength >> 8, 1);
compressHeader.writeUInt8(seqId, 3);
compressHeader.writeUInt8(packetLen & 0xff, 4);
compressHeader.writeUInt16LE(packetLen >> 8, 5);
connection.writeUncompressed(compressHeader);
connection.writeUncompressed(compressed);
} else {
// http://dev.mysql.com/doc/internals/en/uncompressed-payload.html
// To send an uncompressed payload:
// - set length of payload before compression to 0
// - the compressed payload contains the uncompressed payload instead.
compressedLength = packetLen;
packetLen = 0;
compressHeader.writeUInt8(compressedLength & 0xff, 0);
compressHeader.writeUInt16LE(compressedLength >> 8, 1);
compressHeader.writeUInt8(seqId, 3);
compressHeader.writeUInt8(packetLen & 0xff, 4);
compressHeader.writeUInt16LE(packetLen >> 8, 5);
connection.writeUncompressed(compressHeader);
connection.writeUncompressed(buffer);
}
task.done();
});
});
})(connection.compressedSequenceId);
connection._bumpCompressedSequenceId(1);
}
function enableCompression(connection) {
connection._lastWrittenPacketId = 0;
connection._lastReceivedPacketId = 0;
connection._handleCompressedPacket = handleCompressedPacket;
connection._inflatedPacketsParser = new PacketParser(p => {
connection.handlePacket(p);
}, 4);
connection._inflatedPacketsParser._lastPacket = 0;
connection.packetParser = new PacketParser(packet => {
connection._handleCompressedPacket(packet);
}, 7);
connection.writeUncompressed = connection.write;
connection.write = writeCompressed;
const seqqueue = require('seq-queue');
connection.inflateQueue = seqqueue.createQueue();
connection.deflateQueue = seqqueue.createQueue();
}
module.exports = {
enableCompression: enableCompression
};

900
node_modules/mysql2/lib/connection.js generated vendored Normal file
View File

@ -0,0 +1,900 @@
'use strict';
const Net = require('net');
const Tls = require('tls');
const Timers = require('timers');
const EventEmitter = require('events').EventEmitter;
const Readable = require('stream').Readable;
const Queue = require('denque');
const SqlString = require('sqlstring');
const LRU = require('lru-cache');
const PacketParser = require('./packet_parser.js');
const Packets = require('./packets/index.js');
const Commands = require('./commands/index.js');
const ConnectionConfig = require('./connection_config.js');
const CharsetToEncoding = require('./constants/charset_encodings.js');
let _connectionId = 0;
let convertNamedPlaceholders = null;
class Connection extends EventEmitter {
constructor(opts) {
super();
this.config = opts.config;
// TODO: fill defaults
// if no params, connect to /var/lib/mysql/mysql.sock ( /tmp/mysql.sock on OSX )
// if host is given, connect to host:3306
// TODO: use `/usr/local/mysql/bin/mysql_config --socket` output? as default socketPath
// if there is no host/port and no socketPath parameters?
if (!opts.config.stream) {
if (opts.config.socketPath) {
this.stream = Net.connect(opts.config.socketPath);
} else {
this.stream = Net.connect(
opts.config.port,
opts.config.host
);
// Enable keep-alive on the socket. It's disabled by default, but the
// user can enable it and supply an initial delay.
this.stream.setKeepAlive(true, this.config.keepAliveInitialDelay);
}
// if stream is a function, treat it as "stream agent / factory"
} else if (typeof opts.config.stream === 'function') {
this.stream = opts.config.stream(opts);
} else {
this.stream = opts.config.stream;
}
this._internalId = _connectionId++;
this._commands = new Queue();
this._command = null;
this._paused = false;
this._paused_packets = new Queue();
this._statements = new LRU({
max: this.config.maxPreparedStatements,
dispose: function(key, statement) {
statement.close();
}
});
this.serverCapabilityFlags = 0;
this.authorized = false;
this.sequenceId = 0;
this.compressedSequenceId = 0;
this.threadId = null;
this._handshakePacket = null;
this._fatalError = null;
this._protocolError = null;
this._outOfOrderPackets = [];
this.clientEncoding = CharsetToEncoding[this.config.charsetNumber];
this.stream.on('error', this._handleNetworkError.bind(this));
// see https://gist.github.com/khoomeister/4985691#use-that-instead-of-bind
this.packetParser = new PacketParser(p => {
this.handlePacket(p);
});
this.stream.on('data', data => {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
this.packetParser.execute(data);
});
this.stream.on('close', () => {
// we need to set this flag everywhere where we want connection to close
if (this._closing) {
return;
}
if (!this._protocolError) {
// no particular error message before disconnect
this._protocolError = new Error(
'Connection lost: The server closed the connection.'
);
this._protocolError.fatal = true;
this._protocolError.code = 'PROTOCOL_CONNECTION_LOST';
}
this._notifyError(this._protocolError);
});
let handshakeCommand;
if (!this.config.isServer) {
handshakeCommand = new Commands.ClientHandshake(this.config.clientFlags);
handshakeCommand.on('end', () => {
// this happens when handshake finishes early and first packet is error
// and not server hello ( for example, 'Too many connactions' error)
if (!handshakeCommand.handshake) {
return;
}
this._handshakePacket = handshakeCommand.handshake;
this.threadId = handshakeCommand.handshake.connectionId;
this.emit('connect', handshakeCommand.handshake);
});
handshakeCommand.on('error', err => {
this._closing = true;
this._notifyError(err);
});
this.addCommand(handshakeCommand);
}
// in case there was no initiall handshake but we need to read sting, assume it utf-8
// most common example: "Too many connections" error ( packet is sent immediately on connection attempt, we don't know server encoding yet)
// will be overwrittedn with actial encoding value as soon as server handshake packet is received
this.serverEncoding = 'utf8';
if (this.config.connectTimeout) {
const timeoutHandler = this._handleTimeoutError.bind(this);
this.connectTimeout = Timers.setTimeout(
timeoutHandler,
this.config.connectTimeout
);
}
}
promise(promiseImpl) {
const PromiseConnection = require('../promise').PromiseConnection;
return new PromiseConnection(this, promiseImpl);
}
_addCommandClosedState(cmd) {
const err = new Error(
"Can't add new command when connection is in closed state"
);
err.fatal = true;
if (cmd.onResult) {
cmd.onResult(err);
} else {
this.emit('error', err);
}
}
_handleFatalError(err) {
err.fatal = true;
// stop receiving packets
this.stream.removeAllListeners('data');
this.addCommand = this._addCommandClosedState;
this.write = () => {
this.emit('error', new Error("Can't write in closed state"));
};
this._notifyError(err);
this._fatalError = err;
}
_handleNetworkError(err) {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
// Do not throw an error when a connection ends with a RST,ACK packet
if (err.errno === 'ECONNRESET' && this._closing) {
return;
}
this._handleFatalError(err);
}
_handleTimeoutError() {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
this.stream.destroy && this.stream.destroy();
const err = new Error('connect ETIMEDOUT');
err.errorno = 'ETIMEDOUT';
err.code = 'ETIMEDOUT';
err.syscall = 'connect';
this._handleNetworkError(err);
}
// notify all commands in the queue and bubble error as connection "error"
// called on stream error or unexpected termination
_notifyError(err) {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
// prevent from emitting 'PROTOCOL_CONNECTION_LOST' after EPIPE or ECONNRESET
if (this._fatalError) {
return;
}
let command;
// if there is no active command, notify connection
// if there are commands and all of them have callbacks, pass error via callback
let bubbleErrorToConnection = !this._command;
if (this._command && this._command.onResult) {
this._command.onResult(err);
this._command = null;
// connection handshake is special because we allow it to be implicit
// if error happened during handshake, but there are others commands in queue
// then bubble error to other commands and not to connection
} else if (
!(
this._command &&
this._command.constructor === Commands.ClientHandshake &&
this._commands.length > 0
)
) {
bubbleErrorToConnection = true;
}
while ((command = this._commands.shift())) {
if (command.onResult) {
command.onResult(err);
} else {
bubbleErrorToConnection = true;
}
}
// notify connection if some comands in the queue did not have callbacks
// or if this is pool connection ( so it can be removed from pool )
if (bubbleErrorToConnection || this._pool) {
this.emit('error', err);
}
}
write(buffer) {
const result = this.stream.write(buffer, err => {
if (err) {
this._handleNetworkError(err);
}
});
if (!result) {
this.stream.emit('pause');
}
}
// http://dev.mysql.com/doc/internals/en/sequence-id.html
//
// The sequence-id is incremented with each packet and may wrap around.
// It starts at 0 and is reset to 0 when a new command
// begins in the Command Phase.
// http://dev.mysql.com/doc/internals/en/example-several-mysql-packets.html
_resetSequenceId() {
this.sequenceId = 0;
this.compressedSequenceId = 0;
}
_bumpCompressedSequenceId(numPackets) {
this.compressedSequenceId += numPackets;
this.compressedSequenceId %= 256;
}
_bumpSequenceId(numPackets) {
this.sequenceId += numPackets;
this.sequenceId %= 256;
}
writePacket(packet) {
const MAX_PACKET_LENGTH = 16777215;
const length = packet.length();
let chunk, offset, header;
if (length < MAX_PACKET_LENGTH) {
packet.writeHeader(this.sequenceId);
if (this.config.debug) {
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} <== ${this._command._commandName}#${this._command.stateName()}(${[this.sequenceId, packet._name, packet.length()].join(',')})`
);
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} <== ${packet.buffer.toString('hex')}`
);
}
this._bumpSequenceId(1);
this.write(packet.buffer);
} else {
if (this.config.debug) {
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} <== Writing large packet, raw content not written:`
);
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} <== ${this._command._commandName}#${this._command.stateName()}(${[this.sequenceId, packet._name, packet.length()].join(',')})`
);
}
for (offset = 4; offset < 4 + length; offset += MAX_PACKET_LENGTH) {
chunk = packet.buffer.slice(offset, offset + MAX_PACKET_LENGTH);
if (chunk.length === MAX_PACKET_LENGTH) {
header = Buffer.from([0xff, 0xff, 0xff, this.sequenceId]);
} else {
header = Buffer.from([
chunk.length & 0xff,
(chunk.length >> 8) & 0xff,
(chunk.length >> 16) & 0xff,
this.sequenceId
]);
}
this._bumpSequenceId(1);
this.write(header);
this.write(chunk);
}
}
}
// 0.11+ environment
startTLS(onSecure) {
if (this.config.debug) {
// eslint-disable-next-line no-console
console.log('Upgrading connection to TLS');
}
const secureContext = Tls.createSecureContext({
ca: this.config.ssl.ca,
cert: this.config.ssl.cert,
ciphers: this.config.ssl.ciphers,
key: this.config.ssl.key,
passphrase: this.config.ssl.passphrase,
minVersion: this.config.ssl.minVersion
});
const rejectUnauthorized = this.config.ssl.rejectUnauthorized;
let secureEstablished = false;
const secureSocket = new Tls.TLSSocket(this.stream, {
rejectUnauthorized: rejectUnauthorized,
requestCert: true,
secureContext: secureContext,
isServer: false
});
// error handler for secure socket
secureSocket.on('_tlsError', err => {
if (secureEstablished) {
this._handleNetworkError(err);
} else {
onSecure(err);
}
});
secureSocket.on('secure', () => {
secureEstablished = true;
onSecure(rejectUnauthorized ? secureSocket.ssl.verifyError() : null);
});
secureSocket.on('data', data => {
this.packetParser.execute(data);
});
this.write = buffer => {
secureSocket.write(buffer);
};
// start TLS communications
secureSocket._start();
}
pipe() {
if (this.stream instanceof Net.Stream) {
this.stream.ondata = (data, start, end) => {
this.packetParser.execute(data, start, end);
};
} else {
this.stream.on('data', data => {
this.packetParser.execute(
data.parent,
data.offset,
data.offset + data.length
);
});
}
}
protocolError(message, code) {
const err = new Error(message);
err.fatal = true;
err.code = code || 'PROTOCOL_ERROR';
this.emit('error', err);
}
handlePacket(packet) {
if (this._paused) {
this._paused_packets.push(packet);
return;
}
if (packet) {
if (this.sequenceId !== packet.sequenceId) {
const err = new Error(
`Warning: got packets out of order. Expected ${this.sequenceId} but received ${packet.sequenceId}`
);
err.expected = this.sequenceId;
err.received = packet.sequenceId;
this.emit('warn', err); // REVIEW
// eslint-disable-next-line no-console
console.error(err.message);
}
this._bumpSequenceId(packet.numPackets);
}
if (this.config.debug) {
if (packet) {
// eslint-disable-next-line no-console
console.log(
` raw: ${packet.buffer
.slice(packet.offset, packet.offset + packet.length())
.toString('hex')}`
);
// eslint-disable-next-line no-console
console.trace();
const commandName = this._command
? this._command._commandName
: '(no command)';
const stateName = this._command
? this._command.stateName()
: '(no command)';
// eslint-disable-next-line no-console
console.log(
`${this._internalId} ${this.connectionId} ==> ${commandName}#${stateName}(${[packet.sequenceId, packet.type(), packet.length()].join(',')})`
);
}
}
if (!this._command) {
this.protocolError(
'Unexpected packet while no commands in the queue',
'PROTOCOL_UNEXPECTED_PACKET'
);
this.close();
return;
}
const done = this._command.execute(packet, this);
if (done) {
this._command = this._commands.shift();
if (this._command) {
this.sequenceId = 0;
this.compressedSequenceId = 0;
this.handlePacket();
}
}
}
addCommand(cmd) {
// this.compressedSequenceId = 0;
// this.sequenceId = 0;
if (this.config.debug) {
const commandName = cmd.constructor.name;
// eslint-disable-next-line no-console
console.log(`Add command: ${commandName}`);
cmd._commandName = commandName;
}
if (!this._command) {
this._command = cmd;
this.handlePacket();
} else {
this._commands.push(cmd);
}
return cmd;
}
format(sql, values) {
if (typeof this.config.queryFormat === 'function') {
return this.config.queryFormat.call(
this,
sql,
values,
this.config.timezone
);
}
const opts = {
sql: sql,
values: values
};
this._resolveNamedPlaceholders(opts);
return SqlString.format(
opts.sql,
opts.values,
this.config.stringifyObjects,
this.config.timezone
);
}
escape(value) {
return SqlString.escape(value, false, this.config.timezone);
}
escapeId(value) {
return SqlString.escapeId(value, false);
}
raw(sql) {
return SqlString.raw(sql);
}
_resolveNamedPlaceholders(options) {
let unnamed;
if (this.config.namedPlaceholders || options.namedPlaceholders) {
if (convertNamedPlaceholders === null) {
convertNamedPlaceholders = require('named-placeholders')();
}
unnamed = convertNamedPlaceholders(options.sql, options.values);
options.sql = unnamed[0];
options.values = unnamed[1];
}
}
query(sql, values, cb) {
let cmdQuery;
if (sql.constructor === Commands.Query) {
cmdQuery = sql;
} else {
cmdQuery = Connection.createQuery(sql, values, cb, this.config);
}
this._resolveNamedPlaceholders(cmdQuery);
const rawSql = this.format(cmdQuery.sql, cmdQuery.values !== undefined ? cmdQuery.values : []);
cmdQuery.sql = rawSql;
return this.addCommand(cmdQuery);
}
pause() {
this._paused = true;
this.stream.pause();
}
resume() {
let packet;
this._paused = false;
while ((packet = this._paused_packets.shift())) {
this.handlePacket(packet);
// don't resume if packet hander paused connection
if (this._paused) {
return;
}
}
this.stream.resume();
}
// TODO: named placeholders support
prepare(options, cb) {
if (typeof options === 'string') {
options = { sql: options };
}
return this.addCommand(new Commands.Prepare(options, cb));
}
unprepare(sql) {
let options = {};
if (typeof sql === 'object') {
options = sql;
} else {
options.sql = sql;
}
const key = Connection.statementKey(options);
const stmt = this._statements.get(key);
if (stmt) {
this._statements.del(key);
stmt.close();
}
return stmt;
}
execute(sql, values, cb) {
let options = {};
if (typeof sql === 'object') {
// execute(options, cb)
options = sql;
if (typeof values === 'function') {
cb = values;
} else {
options.values = options.values || values;
}
} else if (typeof values === 'function') {
// execute(sql, cb)
cb = values;
options.sql = sql;
options.values = undefined;
} else {
// execute(sql, values, cb)
options.sql = sql;
options.values = values;
}
this._resolveNamedPlaceholders(options);
// check for values containing undefined
if (options.values) {
//If namedPlaceholder is not enabled and object is passed as bind parameters
if (!Array.isArray(options.values)) {
throw new TypeError(
'Bind parameters must be array if namedPlaceholders parameter is not enabled'
);
}
options.values.forEach(val => {
//If namedPlaceholder is not enabled and object is passed as bind parameters
if (!Array.isArray(options.values)) {
throw new TypeError(
'Bind parameters must be array if namedPlaceholders parameter is not enabled'
);
}
if (val === undefined) {
throw new TypeError(
'Bind parameters must not contain undefined. To pass SQL NULL specify JS null'
);
}
if (typeof val === 'function') {
throw new TypeError(
'Bind parameters must not contain function(s). To pass the body of a function as a string call .toString() first'
);
}
});
}
const executeCommand = new Commands.Execute(options, cb);
const prepareCommand = new Commands.Prepare(options, (err, stmt) => {
if (err) {
// skip execute command if prepare failed, we have main
// combined callback here
executeCommand.start = function() {
return null;
};
if (cb) {
cb(err);
} else {
executeCommand.emit('error', err);
}
executeCommand.emit('end');
return;
}
executeCommand.statement = stmt;
});
this.addCommand(prepareCommand);
this.addCommand(executeCommand);
return executeCommand;
}
changeUser(options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
const charsetNumber = options.charset
? ConnectionConfig.getCharsetNumber(options.charset)
: this.config.charsetNumber;
return this.addCommand(
new Commands.ChangeUser(
{
user: options.user || this.config.user,
password: options.password || this.config.password,
passwordSha1: options.passwordSha1 || this.config.passwordSha1,
database: options.database || this.config.database,
timeout: options.timeout,
charsetNumber: charsetNumber,
currentConfig: this.config
},
err => {
if (err) {
err.fatal = true;
}
if (callback) {
callback(err);
}
}
)
);
}
// transaction helpers
beginTransaction(cb) {
return this.query('START TRANSACTION', cb);
}
commit(cb) {
return this.query('COMMIT', cb);
}
rollback(cb) {
return this.query('ROLLBACK', cb);
}
ping(cb) {
return this.addCommand(new Commands.Ping(cb));
}
_registerSlave(opts, cb) {
return this.addCommand(new Commands.RegisterSlave(opts, cb));
}
_binlogDump(opts, cb) {
return this.addCommand(new Commands.BinlogDump(opts, cb));
}
// currently just alias to close
destroy() {
this.close();
}
close() {
if (this.connectTimeout) {
Timers.clearTimeout(this.connectTimeout);
this.connectTimeout = null;
}
this._closing = true;
this.stream.end();
this.addCommand = this._addCommandClosedState;
}
createBinlogStream(opts) {
// TODO: create proper stream class
// TODO: use through2
let test = 1;
const stream = new Readable({ objectMode: true });
stream._read = function() {
return {
data: test++
};
};
this._registerSlave(opts, () => {
const dumpCmd = this._binlogDump(opts);
dumpCmd.on('event', ev => {
stream.push(ev);
});
dumpCmd.on('eof', () => {
stream.push(null);
// if non-blocking, then close stream to prevent errors
if (opts.flags && opts.flags & 0x01) {
this.close();
}
});
// TODO: pipe errors as well
});
return stream;
}
connect(cb) {
if (!cb) {
return;
}
if (this._fatalError || this._protocolError) {
return cb(this._fatalError || this._protocolError);
}
if (this._handshakePacket) {
return cb(null, this);
}
let connectCalled = 0;
function callbackOnce(isErrorHandler) {
return function(param) {
if (!connectCalled) {
if (isErrorHandler) {
cb(param);
} else {
cb(null, param);
}
}
connectCalled = 1;
};
}
this.once('error', callbackOnce(true));
this.once('connect', callbackOnce(false));
}
// ===================================
// outgoing server connection methods
// ===================================
writeColumns(columns) {
this.writePacket(Packets.ResultSetHeader.toPacket(columns.length));
columns.forEach(column => {
this.writePacket(
Packets.ColumnDefinition.toPacket(column, this.serverConfig.encoding)
);
});
this.writeEof();
}
// row is array of columns, not hash
writeTextRow(column) {
this.writePacket(
Packets.TextRow.toPacket(column, this.serverConfig.encoding)
);
}
writeTextResult(rows, columns) {
this.writeColumns(columns);
rows.forEach(row => {
const arrayRow = new Array(columns.length);
columns.forEach(column => {
arrayRow.push(row[column.name]);
});
this.writeTextRow(arrayRow);
});
this.writeEof();
}
writeEof(warnings, statusFlags) {
this.writePacket(Packets.EOF.toPacket(warnings, statusFlags));
}
writeOk(args) {
if (!args) {
args = { affectedRows: 0 };
}
this.writePacket(Packets.OK.toPacket(args, this.serverConfig.encoding));
}
writeError(args) {
// if we want to send error before initial hello was sent, use default encoding
const encoding = this.serverConfig ? this.serverConfig.encoding : 'cesu8';
this.writePacket(Packets.Error.toPacket(args, encoding));
}
serverHandshake(args) {
this.serverConfig = args;
this.serverConfig.encoding =
CharsetToEncoding[this.serverConfig.characterSet];
return this.addCommand(new Commands.ServerHandshake(args));
}
// ===============================================================
end(callback) {
if (this.config.isServer) {
this._closing = true;
const quitCmd = new EventEmitter();
setImmediate(() => {
this.stream.end();
quitCmd.emit('end');
});
return quitCmd;
}
// trigger error if more commands enqueued after end command
const quitCmd = this.addCommand(new Commands.Quit(callback));
this.addCommand = this._addCommandClosedState;
return quitCmd;
}
static createQuery(sql, values, cb, config) {
let options = {
rowsAsArray: config.rowsAsArray
};
if (typeof sql === 'object') {
// query(options, cb)
options = sql;
if (typeof values === 'function') {
cb = values;
} else if (values !== undefined) {
options.values = values;
}
} else if (typeof values === 'function') {
// query(sql, cb)
cb = values;
options.sql = sql;
options.values = undefined;
} else {
// query(sql, values, cb)
options.sql = sql;
options.values = values;
}
return new Commands.Query(options, cb);
}
static statementKey(options) {
return (
`${typeof options.nestTables}/${options.nestTables}/${options.rowsAsArray}${options.sql}`
);
}
}
if (Tls.TLSSocket) {
// not supported
} else {
Connection.prototype.startTLS = function _startTLS(onSecure) {
if (this.config.debug) {
// eslint-disable-next-line no-console
console.log('Upgrading connection to TLS');
}
const crypto = require('crypto');
const config = this.config;
const stream = this.stream;
const rejectUnauthorized = this.config.ssl.rejectUnauthorized;
const credentials = crypto.createCredentials({
key: config.ssl.key,
cert: config.ssl.cert,
passphrase: config.ssl.passphrase,
ca: config.ssl.ca,
ciphers: config.ssl.ciphers
});
const securePair = Tls.createSecurePair(
credentials,
false,
true,
rejectUnauthorized
);
if (stream.ondata) {
stream.ondata = null;
}
stream.removeAllListeners('data');
stream.pipe(securePair.encrypted);
securePair.encrypted.pipe(stream);
securePair.cleartext.on('data', data => {
this.packetParser.execute(data);
});
this.write = function(buffer) {
securePair.cleartext.write(buffer);
};
securePair.on('secure', () => {
onSecure(rejectUnauthorized ? securePair.ssl.verifyError() : null);
});
};
}
module.exports = Connection;

262
node_modules/mysql2/lib/connection_config.js generated vendored Normal file
View File

@ -0,0 +1,262 @@
'use strict';
const urlParse = require('url').parse;
const ClientConstants = require('./constants/client');
const Charsets = require('./constants/charsets');
let SSLProfiles = null;
const validOptions = {
authPlugins: 1,
authSwitchHandler: 1,
bigNumberStrings: 1,
charset: 1,
charsetNumber: 1,
compress: 1,
connectAttributes: 1,
connectTimeout: 1,
database: 1,
dateStrings: 1,
debug: 1,
decimalNumbers: 1,
enableKeepAlive: 1,
flags: 1,
host: 1,
insecureAuth: 1,
isServer: 1,
keepAliveInitialDelay: 1,
localAddress: 1,
maxPreparedStatements: 1,
multipleStatements: 1,
namedPlaceholders: 1,
nestTables: 1,
password: 1,
passwordSha1: 1,
pool: 1,
port: 1,
queryFormat: 1,
rowsAsArray: 1,
socketPath: 1,
ssl: 1,
stream: 1,
stringifyObjects: 1,
supportBigNumbers: 1,
timezone: 1,
trace: 1,
typeCast: 1,
uri: 1,
user: 1,
// These options are used for Pool
connectionLimit: 1,
Promise: 1,
queueLimit: 1,
waitForConnections: 1
};
class ConnectionConfig {
constructor(options) {
if (typeof options === 'string') {
options = ConnectionConfig.parseUrl(options);
} else if (options && options.uri) {
const uriOptions = ConnectionConfig.parseUrl(options.uri);
for (const key in uriOptions) {
if (!Object.prototype.hasOwnProperty.call(uriOptions, key)) continue;
if (options[key]) continue;
options[key] = uriOptions[key];
}
}
for (const key in options) {
if (!Object.prototype.hasOwnProperty.call(options, key)) continue;
if (validOptions[key] !== 1) {
// REVIEW: Should this be emitted somehow?
// eslint-disable-next-line no-console
console.error(
`Ignoring invalid configuration option passed to Connection: ${key}. This is currently a warning, but in future versions of MySQL2, an error will be thrown if you pass an invalid configuration option to a Connection`
);
}
}
this.isServer = options.isServer;
this.stream = options.stream;
this.host = options.host || 'localhost';
this.port = options.port || 3306;
this.localAddress = options.localAddress;
this.socketPath = options.socketPath;
this.user = options.user || undefined;
this.password = options.password || undefined;
this.passwordSha1 = options.passwordSha1 || undefined;
this.database = options.database;
this.connectTimeout = isNaN(options.connectTimeout)
? 10 * 1000
: options.connectTimeout;
this.insecureAuth = options.insecureAuth || false;
this.supportBigNumbers = options.supportBigNumbers || false;
this.bigNumberStrings = options.bigNumberStrings || false;
this.decimalNumbers = options.decimalNumbers || false;
this.dateStrings = options.dateStrings || false;
this.debug = options.debug;
this.trace = options.trace !== false;
this.stringifyObjects = options.stringifyObjects || false;
this.enableKeepAlive = !!options.enableKeepAlive;
this.keepAliveInitialDelay = options.keepAliveInitialDelay || 0;
if (
options.timezone &&
!/^(?:local|Z|[ +-]\d\d:\d\d)$/.test(options.timezone)
) {
// strictly supports timezones specified by mysqljs/mysql:
// https://github.com/mysqljs/mysql#user-content-connection-options
// eslint-disable-next-line no-console
console.error(
`Ignoring invalid timezone passed to Connection: ${options.timezone}. This is currently a warning, but in future versions of MySQL2, an error will be thrown if you pass an invalid configuration option to a Connection`
);
// SqlStrings falls back to UTC on invalid timezone
this.timezone = 'Z';
} else {
this.timezone = options.timezone || 'local';
}
this.queryFormat = options.queryFormat;
this.pool = options.pool || undefined;
this.ssl =
typeof options.ssl === 'string'
? ConnectionConfig.getSSLProfile(options.ssl)
: options.ssl || false;
this.multipleStatements = options.multipleStatements || false;
this.rowsAsArray = options.rowsAsArray || false;
this.namedPlaceholders = options.namedPlaceholders || false;
this.nestTables =
options.nestTables === undefined ? undefined : options.nestTables;
this.typeCast = options.typeCast === undefined ? true : options.typeCast;
if (this.timezone[0] === ' ') {
// "+" is a url encoded char for space so it
// gets translated to space when giving a
// connection string..
this.timezone = `+${this.timezone.substr(1)}`;
}
if (this.ssl) {
if (typeof this.ssl !== 'object') {
throw new TypeError(
`SSL profile must be an object, instead it's a ${typeof this.ssl}`
);
}
// Default rejectUnauthorized to true
this.ssl.rejectUnauthorized = this.ssl.rejectUnauthorized !== false;
}
this.maxPacketSize = 0;
this.charsetNumber = options.charset
? ConnectionConfig.getCharsetNumber(options.charset)
: options.charsetNumber || Charsets.UTF8MB4_UNICODE_CI;
this.compress = options.compress || false;
this.authPlugins = options.authPlugins;
this.authSwitchHandler = options.authSwitchHandler;
this.clientFlags = ConnectionConfig.mergeFlags(
ConnectionConfig.getDefaultFlags(options),
options.flags || ''
);
this.connectAttributes = options.connectAttributes;
this.maxPreparedStatements = options.maxPreparedStatements || 16000;
}
static mergeFlags(default_flags, user_flags) {
let flags = 0x0,
i;
if (!Array.isArray(user_flags)) {
user_flags = String(user_flags || '')
.toUpperCase()
.split(/\s*,+\s*/);
}
// add default flags unless "blacklisted"
for (i in default_flags) {
if (user_flags.indexOf(`-${default_flags[i]}`) >= 0) {
continue;
}
flags |= ClientConstants[default_flags[i]] || 0x0;
}
// add user flags unless already already added
for (i in user_flags) {
if (user_flags[i][0] === '-') {
continue;
}
if (default_flags.indexOf(user_flags[i]) >= 0) {
continue;
}
flags |= ClientConstants[user_flags[i]] || 0x0;
}
return flags;
}
static getDefaultFlags(options) {
const defaultFlags = [
'LONG_PASSWORD',
'FOUND_ROWS',
'LONG_FLAG',
'CONNECT_WITH_DB',
'ODBC',
'LOCAL_FILES',
'IGNORE_SPACE',
'PROTOCOL_41',
'IGNORE_SIGPIPE',
'TRANSACTIONS',
'RESERVED',
'SECURE_CONNECTION',
'MULTI_RESULTS',
'TRANSACTIONS',
'SESSION_TRACK'
];
if (options && options.multipleStatements) {
defaultFlags.push('MULTI_STATEMENTS');
}
defaultFlags.push('PLUGIN_AUTH');
defaultFlags.push('PLUGIN_AUTH_LENENC_CLIENT_DATA');
if (options && options.connectAttributes) {
defaultFlags.push('CONNECT_ATTRS');
}
return defaultFlags;
}
static getCharsetNumber(charset) {
const num = Charsets[charset.toUpperCase()];
if (num === undefined) {
throw new TypeError(`Unknown charset '${charset}'`);
}
return num;
}
static getSSLProfile(name) {
if (!SSLProfiles) {
SSLProfiles = require('./constants/ssl_profiles.js');
}
const ssl = SSLProfiles[name];
if (ssl === undefined) {
throw new TypeError(`Unknown SSL profile '${name}'`);
}
return ssl;
}
static parseUrl(url) {
url = urlParse(url, true);
const options = {
host: url.hostname,
port: url.port,
database: url.pathname.substr(1)
};
if (url.auth) {
const auth = url.auth.split(':');
options.user = auth[0];
options.password = auth[1];
}
if (url.query) {
for (const key in url.query) {
const value = url.query[key];
try {
// Try to parse this as a JSON expression first
options[key] = JSON.parse(value);
} catch (err) {
// Otherwise assume it is a plain string
options[key] = value;
}
}
}
return options;
}
}
module.exports = ConnectionConfig;

313
node_modules/mysql2/lib/constants/charset_encodings.js generated vendored Normal file
View File

@ -0,0 +1,313 @@
'use strict';
// see tools/generate-charset-mapping.js
// basicalliy result of "SHOW COLLATION" query
module.exports = [
'utf8',
'big5',
'latin2',
'dec8',
'cp850',
'latin1',
'hp8',
'koi8r',
'latin1',
'latin2',
'swe7',
'ascii',
'eucjp',
'sjis',
'cp1251',
'latin1',
'hebrew',
'utf8',
'tis620',
'euckr',
'latin7',
'latin2',
'koi8u',
'cp1251',
'gb2312',
'greek',
'cp1250',
'latin2',
'gbk',
'cp1257',
'latin5',
'latin1',
'armscii8',
'cesu8',
'cp1250',
'ucs2',
'cp866',
'keybcs2',
'macintosh',
'macroman',
'cp852',
'latin7',
'latin7',
'macintosh',
'cp1250',
'utf8',
'utf8',
'latin1',
'latin1',
'latin1',
'cp1251',
'cp1251',
'cp1251',
'macroman',
'utf16',
'utf16',
'utf16-le',
'cp1256',
'cp1257',
'cp1257',
'utf32',
'utf32',
'utf16-le',
'binary',
'armscii8',
'ascii',
'cp1250',
'cp1256',
'cp866',
'dec8',
'greek',
'hebrew',
'hp8',
'keybcs2',
'koi8r',
'koi8u',
'cesu8',
'latin2',
'latin5',
'latin7',
'cp850',
'cp852',
'swe7',
'cesu8',
'big5',
'euckr',
'gb2312',
'gbk',
'sjis',
'tis620',
'ucs2',
'eucjp',
'geostd8',
'geostd8',
'latin1',
'cp932',
'cp932',
'eucjpms',
'eucjpms',
'cp1250',
'utf8',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf16',
'utf8',
'utf8',
'utf8',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'ucs2',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'ucs2',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf32',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'cesu8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'cesu8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'gb18030',
'gb18030',
'gb18030',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8',
'utf8'
];

289
node_modules/mysql2/lib/constants/charsets.js generated vendored Normal file
View File

@ -0,0 +1,289 @@
'use strict';
exports.BIG5_CHINESE_CI = 1;
exports.LATIN2_CZECH_CS = 2;
exports.DEC8_SWEDISH_CI = 3;
exports.CP850_GENERAL_CI = 4;
exports.LATIN1_GERMAN1_CI = 5;
exports.HP8_ENGLISH_CI = 6;
exports.KOI8R_GENERAL_CI = 7;
exports.LATIN1_SWEDISH_CI = 8;
exports.LATIN2_GENERAL_CI = 9;
exports.SWE7_SWEDISH_CI = 10;
exports.ASCII_GENERAL_CI = 11;
exports.UJIS_JAPANESE_CI = 12;
exports.SJIS_JAPANESE_CI = 13;
exports.CP1251_BULGARIAN_CI = 14;
exports.LATIN1_DANISH_CI = 15;
exports.HEBREW_GENERAL_CI = 16;
exports.TIS620_THAI_CI = 18;
exports.EUCKR_KOREAN_CI = 19;
exports.LATIN7_ESTONIAN_CS = 20;
exports.LATIN2_HUNGARIAN_CI = 21;
exports.KOI8U_GENERAL_CI = 22;
exports.CP1251_UKRAINIAN_CI = 23;
exports.GB2312_CHINESE_CI = 24;
exports.GREEK_GENERAL_CI = 25;
exports.CP1250_GENERAL_CI = 26;
exports.LATIN2_CROATIAN_CI = 27;
exports.GBK_CHINESE_CI = 28;
exports.CP1257_LITHUANIAN_CI = 29;
exports.LATIN5_TURKISH_CI = 30;
exports.LATIN1_GERMAN2_CI = 31;
exports.ARMSCII8_GENERAL_CI = 32;
exports.UTF8_GENERAL_CI = 33;
exports.CP1250_CZECH_CS = 34;
exports.UCS2_GENERAL_CI = 35;
exports.CP866_GENERAL_CI = 36;
exports.KEYBCS2_GENERAL_CI = 37;
exports.MACCE_GENERAL_CI = 38;
exports.MACROMAN_GENERAL_CI = 39;
exports.CP852_GENERAL_CI = 40;
exports.LATIN7_GENERAL_CI = 41;
exports.LATIN7_GENERAL_CS = 42;
exports.MACCE_BIN = 43;
exports.CP1250_CROATIAN_CI = 44;
exports.UTF8MB4_GENERAL_CI = 45;
exports.UTF8MB4_BIN = 46;
exports.LATIN1_BIN = 47;
exports.LATIN1_GENERAL_CI = 48;
exports.LATIN1_GENERAL_CS = 49;
exports.CP1251_BIN = 50;
exports.CP1251_GENERAL_CI = 51;
exports.CP1251_GENERAL_CS = 52;
exports.MACROMAN_BIN = 53;
exports.UTF16_GENERAL_CI = 54;
exports.UTF16_BIN = 55;
exports.UTF16LE_GENERAL_CI = 56;
exports.CP1256_GENERAL_CI = 57;
exports.CP1257_BIN = 58;
exports.CP1257_GENERAL_CI = 59;
exports.UTF32_GENERAL_CI = 60;
exports.UTF32_BIN = 61;
exports.UTF16LE_BIN = 62;
exports.BINARY = 63;
exports.ARMSCII8_BIN = 64;
exports.ASCII_BIN = 65;
exports.CP1250_BIN = 66;
exports.CP1256_BIN = 67;
exports.CP866_BIN = 68;
exports.DEC8_BIN = 69;
exports.GREEK_BIN = 70;
exports.HEBREW_BIN = 71;
exports.HP8_BIN = 72;
exports.KEYBCS2_BIN = 73;
exports.KOI8R_BIN = 74;
exports.KOI8U_BIN = 75;
exports.UTF8_TOLOWER_CI = 76;
exports.LATIN2_BIN = 77;
exports.LATIN5_BIN = 78;
exports.LATIN7_BIN = 79;
exports.CP850_BIN = 80;
exports.CP852_BIN = 81;
exports.SWE7_BIN = 82;
exports.UTF8_BIN = 83;
exports.BIG5_BIN = 84;
exports.EUCKR_BIN = 85;
exports.GB2312_BIN = 86;
exports.GBK_BIN = 87;
exports.SJIS_BIN = 88;
exports.TIS620_BIN = 89;
exports.UCS2_BIN = 90;
exports.UJIS_BIN = 91;
exports.GEOSTD8_GENERAL_CI = 92;
exports.GEOSTD8_BIN = 93;
exports.LATIN1_SPANISH_CI = 94;
exports.CP932_JAPANESE_CI = 95;
exports.CP932_BIN = 96;
exports.EUCJPMS_JAPANESE_CI = 97;
exports.EUCJPMS_BIN = 98;
exports.CP1250_POLISH_CI = 99;
exports.UTF16_UNICODE_CI = 101;
exports.UTF16_ICELANDIC_CI = 102;
exports.UTF16_LATVIAN_CI = 103;
exports.UTF16_ROMANIAN_CI = 104;
exports.UTF16_SLOVENIAN_CI = 105;
exports.UTF16_POLISH_CI = 106;
exports.UTF16_ESTONIAN_CI = 107;
exports.UTF16_SPANISH_CI = 108;
exports.UTF16_SWEDISH_CI = 109;
exports.UTF16_TURKISH_CI = 110;
exports.UTF16_CZECH_CI = 111;
exports.UTF16_DANISH_CI = 112;
exports.UTF16_LITHUANIAN_CI = 113;
exports.UTF16_SLOVAK_CI = 114;
exports.UTF16_SPANISH2_CI = 115;
exports.UTF16_ROMAN_CI = 116;
exports.UTF16_PERSIAN_CI = 117;
exports.UTF16_ESPERANTO_CI = 118;
exports.UTF16_HUNGARIAN_CI = 119;
exports.UTF16_SINHALA_CI = 120;
exports.UTF16_GERMAN2_CI = 121;
exports.UTF16_CROATIAN_CI = 122;
exports.UTF16_UNICODE_520_CI = 123;
exports.UTF16_VIETNAMESE_CI = 124;
exports.UCS2_UNICODE_CI = 128;
exports.UCS2_ICELANDIC_CI = 129;
exports.UCS2_LATVIAN_CI = 130;
exports.UCS2_ROMANIAN_CI = 131;
exports.UCS2_SLOVENIAN_CI = 132;
exports.UCS2_POLISH_CI = 133;
exports.UCS2_ESTONIAN_CI = 134;
exports.UCS2_SPANISH_CI = 135;
exports.UCS2_SWEDISH_CI = 136;
exports.UCS2_TURKISH_CI = 137;
exports.UCS2_CZECH_CI = 138;
exports.UCS2_DANISH_CI = 139;
exports.UCS2_LITHUANIAN_CI = 140;
exports.UCS2_SLOVAK_CI = 141;
exports.UCS2_SPANISH2_CI = 142;
exports.UCS2_ROMAN_CI = 143;
exports.UCS2_PERSIAN_CI = 144;
exports.UCS2_ESPERANTO_CI = 145;
exports.UCS2_HUNGARIAN_CI = 146;
exports.UCS2_SINHALA_CI = 147;
exports.UCS2_GERMAN2_CI = 148;
exports.UCS2_CROATIAN_CI = 149;
exports.UCS2_UNICODE_520_CI = 150;
exports.UCS2_VIETNAMESE_CI = 151;
exports.UCS2_GENERAL_MYSQL500_CI = 159;
exports.UTF32_UNICODE_CI = 160;
exports.UTF32_ICELANDIC_CI = 161;
exports.UTF32_LATVIAN_CI = 162;
exports.UTF32_ROMANIAN_CI = 163;
exports.UTF32_SLOVENIAN_CI = 164;
exports.UTF32_POLISH_CI = 165;
exports.UTF32_ESTONIAN_CI = 166;
exports.UTF32_SPANISH_CI = 167;
exports.UTF32_SWEDISH_CI = 168;
exports.UTF32_TURKISH_CI = 169;
exports.UTF32_CZECH_CI = 170;
exports.UTF32_DANISH_CI = 171;
exports.UTF32_LITHUANIAN_CI = 172;
exports.UTF32_SLOVAK_CI = 173;
exports.UTF32_SPANISH2_CI = 174;
exports.UTF32_ROMAN_CI = 175;
exports.UTF32_PERSIAN_CI = 176;
exports.UTF32_ESPERANTO_CI = 177;
exports.UTF32_HUNGARIAN_CI = 178;
exports.UTF32_SINHALA_CI = 179;
exports.UTF32_GERMAN2_CI = 180;
exports.UTF32_CROATIAN_CI = 181;
exports.UTF32_UNICODE_520_CI = 182;
exports.UTF32_VIETNAMESE_CI = 183;
exports.UTF8_UNICODE_CI = 192;
exports.UTF8_ICELANDIC_CI = 193;
exports.UTF8_LATVIAN_CI = 194;
exports.UTF8_ROMANIAN_CI = 195;
exports.UTF8_SLOVENIAN_CI = 196;
exports.UTF8_POLISH_CI = 197;
exports.UTF8_ESTONIAN_CI = 198;
exports.UTF8_SPANISH_CI = 199;
exports.UTF8_SWEDISH_CI = 200;
exports.UTF8_TURKISH_CI = 201;
exports.UTF8_CZECH_CI = 202;
exports.UTF8_DANISH_CI = 203;
exports.UTF8_LITHUANIAN_CI = 204;
exports.UTF8_SLOVAK_CI = 205;
exports.UTF8_SPANISH2_CI = 206;
exports.UTF8_ROMAN_CI = 207;
exports.UTF8_PERSIAN_CI = 208;
exports.UTF8_ESPERANTO_CI = 209;
exports.UTF8_HUNGARIAN_CI = 210;
exports.UTF8_SINHALA_CI = 211;
exports.UTF8_GERMAN2_CI = 212;
exports.UTF8_CROATIAN_CI = 213;
exports.UTF8_UNICODE_520_CI = 214;
exports.UTF8_VIETNAMESE_CI = 215;
exports.UTF8_GENERAL_MYSQL500_CI = 223;
exports.UTF8MB4_UNICODE_CI = 224;
exports.UTF8MB4_ICELANDIC_CI = 225;
exports.UTF8MB4_LATVIAN_CI = 226;
exports.UTF8MB4_ROMANIAN_CI = 227;
exports.UTF8MB4_SLOVENIAN_CI = 228;
exports.UTF8MB4_POLISH_CI = 229;
exports.UTF8MB4_ESTONIAN_CI = 230;
exports.UTF8MB4_SPANISH_CI = 231;
exports.UTF8MB4_SWEDISH_CI = 232;
exports.UTF8MB4_TURKISH_CI = 233;
exports.UTF8MB4_CZECH_CI = 234;
exports.UTF8MB4_DANISH_CI = 235;
exports.UTF8MB4_LITHUANIAN_CI = 236;
exports.UTF8MB4_SLOVAK_CI = 237;
exports.UTF8MB4_SPANISH2_CI = 238;
exports.UTF8MB4_ROMAN_CI = 239;
exports.UTF8MB4_PERSIAN_CI = 240;
exports.UTF8MB4_ESPERANTO_CI = 241;
exports.UTF8MB4_HUNGARIAN_CI = 242;
exports.UTF8MB4_SINHALA_CI = 243;
exports.UTF8MB4_GERMAN2_CI = 244;
exports.UTF8MB4_CROATIAN_CI = 245;
exports.UTF8MB4_UNICODE_520_CI = 246;
exports.UTF8MB4_VIETNAMESE_CI = 247;
exports.GB18030_CHINESE_CI = 248;
exports.GB18030_BIN = 249;
exports.GB18030_UNICODE_520_CI = 250;
exports.UTF8_GENERAL50_CI = 253;
exports.UTF8MB4_0900_AI_CI = 255;
exports.UTF8MB4_CS_0900_AI_CI = 266;
exports.UTF8MB4_DA_0900_AI_CI = 267;
exports.UTF8MB4_DE_PB_0900_AI_CI = 256;
exports.UTF8MB4_EO_0900_AI_CI = 273;
exports.UTF8MB4_ES_0900_AI_CI = 263;
exports.UTF8MB4_ES_TRAD_0900_AI_CI = 270;
exports.UTF8MB4_ET_0900_AI_CI = 262;
exports.UTF8MB4_HR_0900_AI_CI = 275;
exports.UTF8MB4_HU_0900_AI_CI = 274;
exports.UTF8MB4_IS_0900_AI_CI = 257;
exports.UTF8MB4_LA_0900_AI_CI = 271;
exports.UTF8MB4_LT_0900_AI_CI = 268;
exports.UTF8MB4_LV_0900_AI_CI = 258;
exports.UTF8MB4_PL_0900_AI_CI = 261;
exports.UTF8MB4_RO_0900_AI_CI = 259;
exports.UTF8MB4_SK_0900_AI_CI = 269;
exports.UTF8MB4_SL_0900_AI_CI = 260;
exports.UTF8MB4_SV_0900_AI_CI = 264;
exports.UTF8MB4_TR_0900_AI_CI = 265;
exports.UTF8MB4_VI_0900_AI_CI = 277;
// short aliases
exports.BIG5 = exports.BIG5_CHINESE_CI;
exports.DEC8 = exports.DEC8_SWEDISH_CI;
exports.CP850 = exports.CP850_GENERAL_CI;
exports.HP8 = exports.HP8_ENGLISH_CI;
exports.KOI8R = exports.KOI8R_GENERAL_CI;
exports.LATIN1 = exports.LATIN1_SWEDISH_CI;
exports.LATIN2 = exports.LATIN2_GENERAL_CI;
exports.SWE7 = exports.SWE7_SWEDISH_CI;
exports.ASCII = exports.ASCII_GENERAL_CI;
exports.UJIS = exports.UJIS_JAPANESE_CI;
exports.SJIS = exports.SJIS_JAPANESE_CI;
exports.HEBREW = exports.HEBREW_GENERAL_CI;
exports.TIS620 = exports.TIS620_THAI_CI;
exports.EUCKR = exports.EUCKR_KOREAN_CI;
exports.KOI8U = exports.KOI8U_GENERAL_CI;
exports.GB2312 = exports.GB2312_CHINESE_CI;
exports.GREEK = exports.GREEK_GENERAL_CI;
exports.CP1250 = exports.CP1250_GENERAL_CI;
exports.GBK = exports.GBK_CHINESE_CI;
exports.LATIN5 = exports.LATIN5_TURKISH_CI;
exports.ARMSCII8 = exports.ARMSCII8_GENERAL_CI;
exports.UTF8 = exports.UTF8_GENERAL_CI;
exports.UCS2 = exports.UCS2_GENERAL_CI;
exports.CP866 = exports.CP866_GENERAL_CI;
exports.KEYBCS2 = exports.KEYBCS2_GENERAL_CI;
exports.MACCE = exports.MACCE_GENERAL_CI;
exports.MACROMAN = exports.MACROMAN_GENERAL_CI;
exports.CP852 = exports.CP852_GENERAL_CI;
exports.LATIN7 = exports.LATIN7_GENERAL_CI;
exports.UTF8MB4 = exports.UTF8MB4_GENERAL_CI;
exports.CP1251 = exports.CP1251_GENERAL_CI;
exports.UTF16 = exports.UTF16_GENERAL_CI;
exports.UTF16LE = exports.UTF16LE_GENERAL_CI;
exports.CP1256 = exports.CP1256_GENERAL_CI;
exports.CP1257 = exports.CP1257_GENERAL_CI;
exports.UTF32 = exports.UTF32_GENERAL_CI;
exports.CP932 = exports.CP932_JAPANESE_CI;
exports.EUCJPMS = exports.EUCJPMS_JAPANESE_CI;
exports.GB18030 = exports.GB18030_CHINESE_CI;
exports.GEOSTD8 = exports.GEOSTD8_GENERAL_CI;

31
node_modules/mysql2/lib/constants/client.js generated vendored Normal file
View File

@ -0,0 +1,31 @@
'use strict';
// Manually extracted from mysql-5.5.23/include/mysql_com.h
exports.LONG_PASSWORD = 0x00000001; /* new more secure passwords */
exports.FOUND_ROWS = 0x00000002; /* found instead of affected rows */
exports.LONG_FLAG = 0x00000004; /* get all column flags */
exports.CONNECT_WITH_DB = 0x00000008; /* one can specify db on connect */
exports.NO_SCHEMA = 0x00000010; /* don't allow database.table.column */
exports.COMPRESS = 0x00000020; /* can use compression protocol */
exports.ODBC = 0x00000040; /* odbc client */
exports.LOCAL_FILES = 0x00000080; /* can use LOAD DATA LOCAL */
exports.IGNORE_SPACE = 0x00000100; /* ignore spaces before '' */
exports.PROTOCOL_41 = 0x00000200; /* new 4.1 protocol */
exports.INTERACTIVE = 0x00000400; /* this is an interactive client */
exports.SSL = 0x00000800; /* switch to ssl after handshake */
exports.IGNORE_SIGPIPE = 0x00001000; /* IGNORE sigpipes */
exports.TRANSACTIONS = 0x00002000; /* client knows about transactions */
exports.RESERVED = 0x00004000; /* old flag for 4.1 protocol */
exports.SECURE_CONNECTION = 0x00008000; /* new 4.1 authentication */
exports.MULTI_STATEMENTS = 0x00010000; /* enable/disable multi-stmt support */
exports.MULTI_RESULTS = 0x00020000; /* enable/disable multi-results */
exports.PS_MULTI_RESULTS = 0x00040000; /* multi-results in ps-protocol */
exports.PLUGIN_AUTH = 0x00080000; /* client supports plugin authentication */
exports.CONNECT_ATTRS = 0x00100000; /* permits connection attributes */
exports.PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x00200000; /* Understands length-encoded integer for auth response data in Protocol::HandshakeResponse41. */
exports.CAN_HANDLE_EXPIRED_PASSWORDS = 0x00400000; /* Announces support for expired password extension. */
exports.SESSION_TRACK = 0x00800000; /* Can set SERVER_SESSION_STATE_CHANGED in the Status Flags and send session-state change data after a OK packet. */
exports.DEPRECATE_EOF = 0x01000000; /* Can send OK after a Text Resultset. */
exports.SSL_VERIFY_SERVER_CERT = 0x40000000;
exports.REMEMBER_OPTIONS = 0x80000000;

36
node_modules/mysql2/lib/constants/commands.js generated vendored Normal file
View File

@ -0,0 +1,36 @@
'use strict';
module.exports = {
SLEEP: 0x00, // deprecated
QUIT: 0x01,
INIT_DB: 0x02,
QUERY: 0x03,
FIELD_LIST: 0x04,
CREATE_DB: 0x05,
DROP_DB: 0x06,
REFRESH: 0x07,
SHUTDOWN: 0x08,
STATISTICS: 0x09,
PROCESS_INFO: 0x0a, // deprecated
CONNECT: 0x0b, // deprecated
PROCESS_KILL: 0x0c,
DEBUG: 0x0d,
PING: 0x0e,
TIME: 0x0f, // deprecated
DELAYED_INSERT: 0x10, // deprecated
CHANGE_USER: 0x11,
BINLOG_DUMP: 0x12,
TABLE_DUMP: 0x13,
CONNECT_OUT: 0x14,
REGISTER_SLAVE: 0x15,
STMT_PREPARE: 0x16,
STMT_EXECUTE: 0x17,
STMT_SEND_LONG_DATA: 0x18,
STMT_CLOSE: 0x19,
STMT_RESET: 0x1a,
SET_OPTION: 0x1b,
STMT_FETCH: 0x1c,
DAEMON: 0x1d, // deprecated
BINLOG_DUMP_GTID: 0x1e,
UNKNOWN: 0xff // bad!
};

8
node_modules/mysql2/lib/constants/cursor.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
'use strict';
module.exports = {
NO_CURSOR: 0,
READ_ONLY: 1,
FOR_UPDATE: 2,
SCROLLABLE: 3
};

49
node_modules/mysql2/lib/constants/encoding_charset.js generated vendored Normal file
View File

@ -0,0 +1,49 @@
'use strict';
// inverse of charset_encodings
// given encoding, get matching mysql charset number
module.exports = {
big5: 1,
latin2: 2,
dec8: 3,
cp850: 4,
latin1: 5,
hp8: 6,
koi8r: 7,
swe7: 10,
ascii: 11,
eucjp: 12,
sjis: 13,
cp1251: 14,
hebrew: 16,
tis620: 18,
euckr: 19,
latin7: 20,
koi8u: 22,
gb2312: 24,
greek: 25,
cp1250: 26,
gbk: 28,
cp1257: 29,
latin5: 30,
armscii8: 32,
cesu8: 33,
ucs2: 35,
cp866: 36,
keybcs2: 37,
macintosh: 38,
macroman: 39,
cp852: 40,
utf8: 45,
utf8mb4: 45,
utf16: 54,
utf16le: 56,
cp1256: 57,
utf32: 60,
binary: 63,
geostd8: 92,
cp932: 95,
eucjpms: 97,
gb18030: 248
};

1984
node_modules/mysql2/lib/constants/errors.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

20
node_modules/mysql2/lib/constants/field_flags.js generated vendored Normal file
View File

@ -0,0 +1,20 @@
'use strict';
// Manually extracted from mysql-5.5.23/include/mysql_com.h
exports.NOT_NULL = 1; /* Field can't be NULL */
exports.PRI_KEY = 2; /* Field is part of a primary key */
exports.UNIQUE_KEY = 4; /* Field is part of a unique key */
exports.MULTIPLE_KEY = 8; /* Field is part of a key */
exports.BLOB = 16; /* Field is a blob */
exports.UNSIGNED = 32; /* Field is unsigned */
exports.ZEROFILL = 64; /* Field is zerofill */
exports.BINARY = 128; /* Field is binary */
/* The following are only sent to new clients */
exports.ENUM = 256; /* field is an enum */
exports.AUTO_INCREMENT = 512; /* field is a autoincrement field */
exports.TIMESTAMP = 1024; /* Field is a timestamp */
exports.SET = 2048; /* field is a set */
exports.NO_DEFAULT_VALUE = 4096; /* Field doesn't have default value */
exports.ON_UPDATE_NOW = 8192; /* Field is set to NOW on UPDATE */
exports.NUM = 32768; /* Field is num (for clients) */

44
node_modules/mysql2/lib/constants/server_status.js generated vendored Normal file
View File

@ -0,0 +1,44 @@
'use strict';
// Manually extracted from mysql-5.5.23/include/mysql_com.h
/**
Is raised when a multi-statement transaction
has been started, either explicitly, by means
of BEGIN or COMMIT AND CHAIN, or
implicitly, by the first transactional
statement, when autocommit=off.
*/
exports.SERVER_STATUS_IN_TRANS = 1;
exports.SERVER_STATUS_AUTOCOMMIT = 2; /* Server in auto_commit mode */
exports.SERVER_MORE_RESULTS_EXISTS = 8; /* Multi query - next query exists */
exports.SERVER_QUERY_NO_GOOD_INDEX_USED = 16;
exports.SERVER_QUERY_NO_INDEX_USED = 32;
/**
The server was able to fulfill the clients request and opened a
read-only non-scrollable cursor for a query. This flag comes
in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
*/
exports.SERVER_STATUS_CURSOR_EXISTS = 64;
/**
This flag is sent when a read-only cursor is exhausted, in reply to
COM_STMT_FETCH command.
*/
exports.SERVER_STATUS_LAST_ROW_SENT = 128;
exports.SERVER_STATUS_DB_DROPPED = 256; /* A database was dropped */
exports.SERVER_STATUS_NO_BACKSLASH_ESCAPES = 512;
/**
Sent to the client if after a prepared statement reprepare
we discovered that the new statement returns a different
number of result set columns.
*/
exports.SERVER_STATUS_METADATA_CHANGED = 1024;
exports.SERVER_QUERY_WAS_SLOW = 2048;
/**
To mark ResultSet containing output parameter values.
*/
exports.SERVER_PS_OUT_PARAMS = 4096;
exports.SERVER_STATUS_IN_TRANS_READONLY = 0x2000; // in a read-only transaction
exports.SERVER_SESSION_STATE_CHANGED = 0x4000;

11
node_modules/mysql2/lib/constants/session_track.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
'use strict';
exports.SYSTEM_VARIABLES = 0;
exports.SCHEMA = 1;
exports.STATE_CHANGE = 2;
exports.STATE_GTIDS = 3;
exports.TRANSACTION_CHARACTERISTICS = 4;
exports.TRANSACTION_STATE = 5;
exports.FIRST_KEY = exports.SYSTEM_VARIABLES;
exports.LAST_KEY = exports.TRANSACTION_STATE;

1109
node_modules/mysql2/lib/constants/ssl_profiles.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

32
node_modules/mysql2/lib/constants/types.js generated vendored Normal file
View File

@ -0,0 +1,32 @@
'use strict';
// Manually extracted from mysql-5.5.23/include/mysql_com.h
// some more info here: http://dev.mysql.com/doc/refman/5.5/en/c-api-prepared-statement-type-codes.html
exports.DECIMAL = 0x00; // aka DECIMAL (http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html)
exports.TINY = 0x01; // aka TINYINT, 1 byte
exports.SHORT = 0x02; // aka SMALLINT, 2 bytes
exports.LONG = 0x03; // aka INT, 4 bytes
exports.FLOAT = 0x04; // aka FLOAT, 4-8 bytes
exports.DOUBLE = 0x05; // aka DOUBLE, 8 bytes
exports.NULL = 0x06; // NULL (used for prepared statements, I think)
exports.TIMESTAMP = 0x07; // aka TIMESTAMP
exports.LONGLONG = 0x08; // aka BIGINT, 8 bytes
exports.INT24 = 0x09; // aka MEDIUMINT, 3 bytes
exports.DATE = 0x0a; // aka DATE
exports.TIME = 0x0b; // aka TIME
exports.DATETIME = 0x0c; // aka DATETIME
exports.YEAR = 0x0d; // aka YEAR, 1 byte (don't ask)
exports.NEWDATE = 0x0e; // aka ?
exports.VARCHAR = 0x0f; // aka VARCHAR (?)
exports.BIT = 0x10; // aka BIT, 1-8 byte
exports.JSON = 0xf5;
exports.NEWDECIMAL = 0xf6; // aka DECIMAL
exports.ENUM = 0xf7; // aka ENUM
exports.SET = 0xf8; // aka SET
exports.TINY_BLOB = 0xf9; // aka TINYBLOB, TINYTEXT
exports.MEDIUM_BLOB = 0xfa; // aka MEDIUMBLOB, MEDIUMTEXT
exports.LONG_BLOB = 0xfb; // aka LONGBLOG, LONGTEXT
exports.BLOB = 0xfc; // aka BLOB, TEXT
exports.VAR_STRING = 0xfd; // aka VARCHAR, VARBINARY
exports.STRING = 0xfe; // aka CHAR, BINARY
exports.GEOMETRY = 0xff; // aka GEOMETRY

63
node_modules/mysql2/lib/helpers.js generated vendored Normal file
View File

@ -0,0 +1,63 @@
'use strict';
/*
this seems to be not only shorter, but faster than
string.replace(/\\/g, '\\\\').
replace(/\u0008/g, '\\b').
replace(/\t/g, '\\t').
replace(/\n/g, '\\n').
replace(/\f/g, '\\f').
replace(/\r/g, '\\r').
replace(/'/g, '\\\'').
replace(/"/g, '\\"');
or string.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
see http://jsperf.com/string-escape-regexp-vs-json-stringify
*/
function srcEscape(str) {
return JSON.stringify({
[str]: 1
}).slice(1, -3);
}
exports.srcEscape = srcEscape;
let highlightFn;
let cardinalRecommended = false;
try {
highlightFn = require('cardinal').highlight;
} catch (err) {
highlightFn = text => {
if (!cardinalRecommended) {
// eslint-disable-next-line no-console
console.log('For nicer debug output consider install cardinal@^2.0.0');
cardinalRecommended = true;
}
return text;
};
}
/**
* Prints debug message with code frame, will try to use `cardinal` if available.
*/
function printDebugWithCode(msg, code) {
// eslint-disable-next-line no-console
console.log(`\n\n${msg}:\n`);
// eslint-disable-next-line no-console
console.log(`${highlightFn(code)}\n`);
}
exports.printDebugWithCode = printDebugWithCode;
/**
* checks whether the `type` is in the `list`
*/
function typeMatch(type, list, Types) {
if (Array.isArray(list)) {
return list.some(t => type === Types[t]);
}
return !!list;
}
exports.typeMatch = typeMatch;

195
node_modules/mysql2/lib/packet_parser.js generated vendored Normal file
View File

@ -0,0 +1,195 @@
'use strict';
const Packet = require('./packets/packet.js');
const MAX_PACKET_LENGTH = 16777215;
function readPacketLength(b, off) {
const b0 = b[off];
const b1 = b[off + 1];
const b2 = b[off + 2];
if (b1 + b2 === 0) {
return b0;
}
return b0 + (b1 << 8) + (b2 << 16);
}
class PacketParser {
constructor(onPacket, packetHeaderLength) {
// 4 for normal packets, 7 for comprssed protocol packets
if (typeof packetHeaderLength === 'undefined') {
packetHeaderLength = 4;
}
// array of last payload chunks
// only used when current payload is not complete
this.buffer = [];
// total length of chunks on buffer
this.bufferLength = 0;
this.packetHeaderLength = packetHeaderLength;
// incomplete header state: number of header bytes received
this.headerLen = 0;
// expected payload length
this.length = 0;
this.largePacketParts = [];
this.firstPacketSequenceId = 0;
this.onPacket = onPacket;
this.execute = PacketParser.prototype.executeStart;
this._flushLargePacket =
packetHeaderLength === 7
? this._flushLargePacket7
: this._flushLargePacket4;
}
_flushLargePacket4() {
const numPackets = this.largePacketParts.length;
this.largePacketParts.unshift(Buffer.from([0, 0, 0, 0])); // insert header
const body = Buffer.concat(this.largePacketParts);
const packet = new Packet(this.firstPacketSequenceId, body, 0, body.length);
this.largePacketParts.length = 0;
packet.numPackets = numPackets;
this.onPacket(packet);
}
_flushLargePacket7() {
const numPackets = this.largePacketParts.length;
this.largePacketParts.unshift(Buffer.from([0, 0, 0, 0, 0, 0, 0])); // insert header
const body = Buffer.concat(this.largePacketParts);
this.largePacketParts.length = 0;
const packet = new Packet(this.firstPacketSequenceId, body, 0, body.length);
packet.numPackets = numPackets;
this.onPacket(packet);
}
executeStart(chunk) {
let start = 0;
const end = chunk.length;
while (end - start >= 3) {
this.length = readPacketLength(chunk, start);
if (end - start >= this.length + this.packetHeaderLength) {
// at least one full packet
const sequenceId = chunk[start + 3];
if (
this.length < MAX_PACKET_LENGTH &&
this.largePacketParts.length === 0
) {
this.onPacket(
new Packet(
sequenceId,
chunk,
start,
start + this.packetHeaderLength + this.length
)
);
} else {
// first large packet - remember it's id
if (this.largePacketParts.length === 0) {
this.firstPacketSequenceId = sequenceId;
}
this.largePacketParts.push(
chunk.slice(
start + this.packetHeaderLength,
start + this.packetHeaderLength + this.length
)
);
if (this.length < MAX_PACKET_LENGTH) {
this._flushLargePacket();
}
}
start += this.packetHeaderLength + this.length;
} else {
// payload is incomplete
this.buffer = [chunk.slice(start + 3, end)];
this.bufferLength = end - start - 3;
this.execute = PacketParser.prototype.executePayload;
return;
}
}
if (end - start > 0) {
// there is start of length header, but it's not full 3 bytes
this.headerLen = end - start; // 1 or 2 bytes
this.length = chunk[start];
if (this.headerLen === 2) {
this.length = chunk[start] + (chunk[start + 1] << 8);
this.execute = PacketParser.prototype.executeHeader3;
} else {
this.execute = PacketParser.prototype.executeHeader2;
}
}
}
executePayload(chunk) {
let start = 0;
const end = chunk.length;
const remainingPayload =
this.length - this.bufferLength + this.packetHeaderLength - 3;
if (end - start >= remainingPayload) {
// last chunk for payload
const payload = Buffer.allocUnsafe(this.length + this.packetHeaderLength);
let offset = 3;
for (let i = 0; i < this.buffer.length; ++i) {
this.buffer[i].copy(payload, offset);
offset += this.buffer[i].length;
}
chunk.copy(payload, offset, start, start + remainingPayload);
const sequenceId = payload[3];
if (
this.length < MAX_PACKET_LENGTH &&
this.largePacketParts.length === 0
) {
this.onPacket(
new Packet(
sequenceId,
payload,
0,
this.length + this.packetHeaderLength
)
);
} else {
// first large packet - remember it's id
if (this.largePacketParts.length === 0) {
this.firstPacketSequenceId = sequenceId;
}
this.largePacketParts.push(
payload.slice(
this.packetHeaderLength,
this.packetHeaderLength + this.length
)
);
if (this.length < MAX_PACKET_LENGTH) {
this._flushLargePacket();
}
}
this.buffer = [];
this.bufferLength = 0;
this.execute = PacketParser.prototype.executeStart;
start += remainingPayload;
if (end - start > 0) {
return this.execute(chunk.slice(start, end));
}
} else {
this.buffer.push(chunk);
this.bufferLength += chunk.length;
}
return null;
}
executeHeader2(chunk) {
this.length += chunk[0] << 8;
if (chunk.length > 1) {
this.length += chunk[1] << 16;
this.execute = PacketParser.prototype.executePayload;
return this.executePayload(chunk.slice(2));
}
this.execute = PacketParser.prototype.executeHeader3;
return null;
}
executeHeader3(chunk) {
this.length += chunk[0] << 16;
this.execute = PacketParser.prototype.executePayload;
return this.executePayload(chunk.slice(1));
}
}
module.exports = PacketParser;

38
node_modules/mysql2/lib/packets/auth_switch_request.js generated vendored Normal file
View File

@ -0,0 +1,38 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
const Packet = require('../packets/packet');
class AuthSwitchRequest {
constructor(opts) {
this.pluginName = opts.pluginName;
this.pluginData = opts.pluginData;
}
toPacket() {
const length = 6 + this.pluginName.length + this.pluginData.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(0xfe);
// TODO: use server encoding
packet.writeNullTerminatedString(this.pluginName, 'cesu8');
packet.writeBuffer(this.pluginData);
return packet;
}
static fromPacket(packet) {
packet.readInt8(); // marker
// assert marker == 0xfe?
// TODO: use server encoding
const name = packet.readNullTerminatedString('cesu8');
const data = packet.readBuffer();
return new AuthSwitchRequest({
pluginName: name,
pluginData: data
});
}
}
module.exports = AuthSwitchRequest;

View File

@ -0,0 +1,33 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
const Packet = require('../packets/packet');
class AuthSwitchRequestMoreData {
constructor(data) {
this.data = data;
}
toPacket() {
const length = 5 + this.data.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(0x01);
packet.writeBuffer(this.data);
return packet;
}
static fromPacket(packet) {
packet.readInt8(); // marker
const data = packet.readBuffer();
return new AuthSwitchRequestMoreData(data);
}
static verifyMarker(packet) {
return packet.peekByte() === 0x01;
}
}
module.exports = AuthSwitchRequestMoreData;

View File

@ -0,0 +1,30 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
const Packet = require('../packets/packet');
class AuthSwitchResponse {
constructor(data) {
if (!Buffer.isBuffer(data)) {
data = Buffer.from(data);
}
this.data = data;
}
toPacket() {
const length = 4 + this.data.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeBuffer(this.data);
return packet;
}
static fromPacket(packet) {
const data = packet.readBuffer();
return new AuthSwitchResponse(data);
}
}
module.exports = AuthSwitchResponse;

48
node_modules/mysql2/lib/packets/binary_row.js generated vendored Normal file
View File

@ -0,0 +1,48 @@
'use strict';
const Types = require('../constants/types');
const Packet = require('../packets/packet');
const binaryReader = new Array(256);
class BinaryRow {
constructor(columns) {
this.columns = columns || [];
}
toPacket() {
throw new Error('Not implemented');
}
// TODO: complete list of types...
static fromPacket(fields, packet) {
const columns = new Array(fields.length);
packet.readInt8(); // TODO check it's 0
const nullBitmapLength = Math.floor((fields.length + 7 + 2) / 8);
// TODO: read and interpret null bitmap
packet.skip(nullBitmapLength);
for (let i = 0; i < columns.length; ++i) {
columns[i] = binaryReader[fields[i].columnType].apply(packet);
}
return new BinaryRow(columns);
}
}
// TODO: replace with constants.MYSQL_TYPE_*
binaryReader[Types.DECIMAL] = Packet.prototype.readLengthCodedString;
binaryReader[1] = Packet.prototype.readInt8; // tiny
binaryReader[2] = Packet.prototype.readInt16; // short
binaryReader[3] = Packet.prototype.readInt32; // long
binaryReader[4] = Packet.prototype.readFloat; // float
binaryReader[5] = Packet.prototype.readDouble; // double
binaryReader[6] = Packet.prototype.assertInvalid; // null, should be skipped vie null bitmap
binaryReader[7] = Packet.prototype.readTimestamp; // timestamp, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_TIMESTAMP
binaryReader[8] = Packet.prototype.readInt64; // long long
binaryReader[9] = Packet.prototype.readInt32; // int24
binaryReader[10] = Packet.prototype.readTimestamp; // date
binaryReader[11] = Packet.prototype.readTime; // time, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_TIME
binaryReader[12] = Packet.prototype.readDateTime; // datetime, http://dev.mysql.com/doc/internals/en/prepared-statements.html#packet-ProtocolBinary::MYSQL_TYPE_DATETIME
binaryReader[13] = Packet.prototype.readInt16; // year
binaryReader[Types.VAR_STRING] = Packet.prototype.readLengthCodedString; // var string
module.exports = BinaryRow;

33
node_modules/mysql2/lib/packets/binlog_dump.js generated vendored Normal file
View File

@ -0,0 +1,33 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/com-binlog-dump.html#packet-COM_BINLOG_DUMP
const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');
// TODO: add flag to constants
// 0x01 - BINLOG_DUMP_NON_BLOCK
// send EOF instead of blocking
class BinlogDump {
constructor(opts) {
this.binlogPos = opts.binlogPos || 0;
this.serverId = opts.serverId || 0;
this.flags = opts.flags || 0;
this.filename = opts.filename || '';
}
toPacket() {
const length = 15 + Buffer.byteLength(this.filename, 'utf8'); // TODO: should be ascii?
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.BINLOG_DUMP);
packet.writeInt32(this.binlogPos);
packet.writeInt16(this.flags);
packet.writeInt32(this.serverId);
packet.writeString(this.filename);
return packet;
}
}
module.exports = BinlogDump;

View File

@ -0,0 +1,115 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/query-event.html
const keys = {
FLAGS2: 0,
SQL_MODE: 1,
CATALOG: 2,
AUTO_INCREMENT: 3,
CHARSET: 4,
TIME_ZONE: 5,
CATALOG_NZ: 6,
LC_TIME_NAMES: 7,
CHARSET_DATABASE: 8,
TABLE_MAP_FOR_UPDATE: 9,
MASTER_DATA_WRITTEN: 10,
INVOKERS: 11,
UPDATED_DB_NAMES: 12,
MICROSECONDS: 3
};
module.exports = function parseStatusVars(buffer) {
const result = {};
let offset = 0;
let key, length, prevOffset;
while (offset < buffer.length) {
key = buffer[offset++];
switch (key) {
case keys.FLAGS2:
result.flags = buffer.readUInt32LE(offset);
offset += 4;
break;
case keys.SQL_MODE:
// value is 8 bytes, but all dcumented flags are in first 4 bytes
result.sqlMode = buffer.readUInt32LE(offset);
offset += 8;
break;
case keys.CATALOG:
length = buffer[offset++];
result.catalog = buffer.toString('utf8', offset, offset + length);
offset += length + 1; // null byte after string
break;
case keys.CHARSET:
result.clientCharset = buffer.readUInt16LE(offset);
result.connectionCollation = buffer.readUInt16LE(offset + 2);
result.serverCharset = buffer.readUInt16LE(offset + 4);
offset += 6;
break;
case keys.TIME_ZONE:
length = buffer[offset++];
result.timeZone = buffer.toString('utf8', offset, offset + length);
offset += length; // no null byte
break;
case keys.CATALOG_NZ:
length = buffer[offset++];
result.catalogNz = buffer.toString('utf8', offset, offset + length);
offset += length; // no null byte
break;
case keys.LC_TIME_NAMES:
result.lcTimeNames = buffer.readUInt16LE(offset);
offset += 2;
break;
case keys.CHARSET_DATABASE:
result.schemaCharset = buffer.readUInt16LE(offset);
offset += 2;
break;
case keys.TABLE_MAP_FOR_UPDATE:
result.mapForUpdate1 = buffer.readUInt32LE(offset);
result.mapForUpdate2 = buffer.readUInt32LE(offset + 4);
offset += 8;
break;
case keys.MASTER_DATA_WRITTEN:
result.masterDataWritten = buffer.readUInt32LE(offset);
offset += 4;
break;
case keys.INVOKERS:
length = buffer[offset++];
result.invokerUsername = buffer.toString(
'utf8',
offset,
offset + length
);
offset += length;
length = buffer[offset++];
result.invokerHostname = buffer.toString(
'utf8',
offset,
offset + length
);
offset += length;
break;
case keys.UPDATED_DB_NAMES:
length = buffer[offset++];
// length - number of null-terminated strings
result.updatedDBs = []; // we'll store them as array here
for (; length; --length) {
prevOffset = offset;
// fast forward to null terminating byte
while (buffer[offset++] && offset < buffer.length) {
// empty body, everything inside while condition
}
result.updatedDBs.push(
buffer.toString('utf8', prevOffset, offset - 1)
);
}
break;
case keys.MICROSECONDS:
result.microseconds =
// REVIEW: INVALID UNKNOWN VARIABLE!
buffer.readInt16LE(offset) + (buffer[offset + 2] << 16);
offset += 3;
}
}
return result;
};

97
node_modules/mysql2/lib/packets/change_user.js generated vendored Normal file
View File

@ -0,0 +1,97 @@
'use strict';
const CommandCode = require('../constants/commands.js');
const ClientConstants = require('../constants/client.js');
const Packet = require('../packets/packet.js');
const auth41 = require('../auth_41.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
// https://dev.mysql.com/doc/internals/en/com-change-user.html#packet-COM_CHANGE_USER
class ChangeUser {
constructor(opts) {
this.flags = opts.flags;
this.user = opts.user || '';
this.database = opts.database || '';
this.password = opts.password || '';
this.passwordSha1 = opts.passwordSha1;
this.authPluginData1 = opts.authPluginData1;
this.authPluginData2 = opts.authPluginData2;
this.connectAttributes = opts.connectAttrinutes || {};
let authToken;
if (this.passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
this.passwordSha1,
this.authPluginData1,
this.authPluginData2
);
} else {
authToken = auth41.calculateToken(
this.password,
this.authPluginData1,
this.authPluginData2
);
}
this.authToken = authToken;
this.charsetNumber = opts.charsetNumber;
}
// TODO
// ChangeUser.fromPacket = function(packet)
// };
serializeToBuffer(buffer) {
const isSet = flag => this.flags & ClientConstants[flag];
const packet = new Packet(0, buffer, 0, buffer.length);
packet.offset = 4;
const encoding = CharsetToEncoding[this.charsetNumber];
packet.writeInt8(CommandCode.CHANGE_USER);
packet.writeNullTerminatedString(this.user, encoding);
if (isSet('SECURE_CONNECTION')) {
packet.writeInt8(this.authToken.length);
packet.writeBuffer(this.authToken);
} else {
packet.writeBuffer(this.authToken);
packet.writeInt8(0);
}
packet.writeNullTerminatedString(this.database, encoding);
packet.writeInt16(this.charsetNumber);
if (isSet('PLUGIN_AUTH')) {
// TODO: read this from parameters
packet.writeNullTerminatedString('mysql_native_password', 'latin1');
}
if (isSet('CONNECT_ATTRS')) {
const connectAttributes = this.connectAttributes;
const attrNames = Object.keys(connectAttributes);
let keysLength = 0;
for (let k = 0; k < attrNames.length; ++k) {
keysLength += Packet.lengthCodedStringLength(attrNames[k], encoding);
keysLength += Packet.lengthCodedStringLength(
connectAttributes[attrNames[k]],
encoding
);
}
packet.writeLengthCodedNumber(keysLength);
for (let k = 0; k < attrNames.length; ++k) {
packet.writeLengthCodedString(attrNames[k], encoding);
packet.writeLengthCodedString(
connectAttributes[attrNames[k]],
encoding
);
}
}
return packet;
}
toPacket() {
if (typeof this.user !== 'string') {
throw new Error('"user" connection config property must be a string');
}
if (typeof this.database !== 'string') {
throw new Error('"database" connection config property must be a string');
}
// dry run: calculate resulting packet length
const p = this.serializeToBuffer(Packet.MockBuffer());
return this.serializeToBuffer(Buffer.allocUnsafe(p.offset));
}
}
module.exports = ChangeUser;

21
node_modules/mysql2/lib/packets/close_statement.js generated vendored Normal file
View File

@ -0,0 +1,21 @@
'use strict';
const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');
class CloseStatement {
constructor(id) {
this.id = id;
}
// note: no response sent back
toPacket() {
const packet = new Packet(0, Buffer.allocUnsafe(9), 0, 9);
packet.offset = 4;
packet.writeInt8(CommandCodes.STMT_CLOSE);
packet.writeInt32(this.id);
return packet;
}
}
module.exports = CloseStatement;

129
node_modules/mysql2/lib/packets/column_definition.js generated vendored Normal file
View File

@ -0,0 +1,129 @@
'use strict';
const Packet = require('../packets/packet');
const StringParser = require('../parsers/string');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const fields = ['catalog', 'schema', 'table', 'orgTable', 'name', 'orgName'];
// creating JS string is relatively expensive (compared to
// reading few bytes from buffer) because all string properties
// except for name are unlikely to be used we postpone
// string conversion until property access
//
// TODO: watch for integration benchmarks (one with real network buffer)
// there could be bad side effect as keeping reference to a buffer makes it
// sit in the memory longer (usually until final .query() callback)
// Latest v8 perform much better in regard to bufferer -> string conversion,
// at some point of time this optimisation might become unnecessary
// see https://github.com/sidorares/node-mysql2/pull/137
//
class ColumnDefinition {
constructor(packet, clientEncoding) {
this._buf = packet.buffer;
this._clientEncoding = clientEncoding;
this._catalogLength = packet.readLengthCodedNumber();
this._catalogStart = packet.offset;
packet.offset += this._catalogLength;
this._schemaLength = packet.readLengthCodedNumber();
this._schemaStart = packet.offset;
packet.offset += this._schemaLength;
this._tableLength = packet.readLengthCodedNumber();
this._tableStart = packet.offset;
packet.offset += this._tableLength;
this._orgTableLength = packet.readLengthCodedNumber();
this._orgTableStart = packet.offset;
packet.offset += this._orgTableLength;
// name is always used, don't make it lazy
const _nameLength = packet.readLengthCodedNumber();
const _nameStart = packet.offset;
packet.offset += _nameLength;
this._orgNameLength = packet.readLengthCodedNumber();
this._orgNameStart = packet.offset;
packet.offset += this._orgNameLength;
packet.skip(1); // length of the following fields (always 0x0c)
this.characterSet = packet.readInt16();
this.encoding = CharsetToEncoding[this.characterSet];
this.name = StringParser.decode(
this._buf.slice(_nameStart, _nameStart + _nameLength),
this.encoding === 'binary' ? this._clientEncoding : this.encoding
);
this.columnLength = packet.readInt32();
this.columnType = packet.readInt8();
this.flags = packet.readInt16();
this.decimals = packet.readInt8();
}
inspect() {
return {
catalog: this.catalog,
schema: this.schema,
name: this.name,
orgName: this.orgName,
table: this.table,
orgTable: this.orgTable,
characterSet: this.characterSet,
columnLength: this.columnLength,
columnType: this.columnType,
flags: this.flags,
decimals: this.decimals
};
}
static toPacket(column, sequenceId) {
let length = 17; // = 4 padding + 1 + 12 for the rest
fields.forEach(field => {
length += Packet.lengthCodedStringLength(
column[field],
CharsetToEncoding[column.characterSet]
);
});
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(sequenceId, buffer, 0, length);
function writeField(name) {
packet.writeLengthCodedString(
column[name],
CharsetToEncoding[column.characterSet]
);
}
packet.offset = 4;
fields.forEach(writeField);
packet.writeInt8(0x0c);
packet.writeInt16(column.characterSet);
packet.writeInt32(column.columnLength);
packet.writeInt8(column.columnType);
packet.writeInt16(column.flags);
packet.writeInt8(column.decimals);
packet.writeInt16(0); // filler
return packet;
}
// node-mysql compatibility: alias "db" to "schema"
get db() {
const start = this._schemaStart;
const end = start._shemaLength;
return this._buf.utf8Slice(start, end);
}
}
const addString = function(name) {
Object.defineProperty(ColumnDefinition.prototype, name, {
get: function() {
const start = this[`_${name}Start`];
const end = start + this[`_${name}Length`];
return StringParser.decode(
this._buf.slice(start, end),
this.encoding === 'binary' ? this._clientEncoding : this.encoding
);
}
});
};
addString('catalog');
addString('schema');
addString('table');
addString('orgTable');
addString('orgName');
module.exports = ColumnDefinition;

150
node_modules/mysql2/lib/packets/execute.js generated vendored Normal file
View File

@ -0,0 +1,150 @@
'use strict';
const CursorType = require('../constants/cursor');
const CommandCodes = require('../constants/commands');
const Types = require('../constants/types');
const Packet = require('../packets/packet');
const CharsetToEncoding = require('../constants/charset_encodings.js');
function isJSON(value) {
return (
Array.isArray(value) ||
value.constructor === Object ||
(typeof value.toJSON === 'function' && !Buffer.isBuffer(value))
);
}
/**
* Converts a value to an object describing type, String/Buffer representation and length
* @param {*} value
*/
function toParameter(value, encoding, timezone) {
let type = Types.VAR_STRING;
let length;
let writer = function(value) {
// eslint-disable-next-line no-invalid-this
return Packet.prototype.writeLengthCodedString.call(this, value, encoding);
};
if (value !== null) {
switch (typeof value) {
case 'undefined':
throw new TypeError('Bind parameters must not contain undefined');
case 'number':
type = Types.DOUBLE;
length = 8;
writer = Packet.prototype.writeDouble;
break;
case 'boolean':
value = value | 0;
type = Types.TINY;
length = 1;
writer = Packet.prototype.writeInt8;
break;
case 'object':
if (Object.prototype.toString.call(value) === '[object Date]') {
type = Types.DATETIME;
length = 12;
writer = function(value) {
// eslint-disable-next-line no-invalid-this
return Packet.prototype.writeDate.call(this, value, timezone);
};
} else if (isJSON(value)) {
value = JSON.stringify(value);
type = Types.JSON;
} else if (Buffer.isBuffer(value)) {
length = Packet.lengthCodedNumberLength(value.length) + value.length;
writer = Packet.prototype.writeLengthCodedBuffer;
}
break;
default:
value = value.toString();
}
} else {
value = '';
type = Types.NULL;
}
if (!length) {
length = Packet.lengthCodedStringLength(value, encoding);
}
return { value, type, length, writer };
}
class Execute {
constructor(id, parameters, charsetNumber, timezone) {
this.id = id;
this.parameters = parameters;
this.encoding = CharsetToEncoding[charsetNumber];
this.timezone = timezone;
}
toPacket() {
// TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?)
// and copy + reallocate if not enough
// 0 + 4 - length, seqId
// 4 + 1 - COM_EXECUTE
// 5 + 4 - stmtId
// 9 + 1 - flags
// 10 + 4 - iteration-count (always 1)
let length = 14;
let parameters;
if (this.parameters && this.parameters.length > 0) {
length += Math.floor((this.parameters.length + 7) / 8);
length += 1; // new-params-bound-flag
length += 2 * this.parameters.length; // type byte for each parameter if new-params-bound-flag is set
parameters = this.parameters.map(value =>
toParameter(value, this.encoding, this.timezone)
);
length += parameters.reduce(
(accumulator, parameter) => accumulator + parameter.length,
0
);
}
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.STMT_EXECUTE);
packet.writeInt32(this.id);
packet.writeInt8(CursorType.NO_CURSOR); // flags
packet.writeInt32(1); // iteration-count, always 1
if (parameters) {
let bitmap = 0;
let bitValue = 1;
parameters.forEach(parameter => {
if (parameter.type === Types.NULL) {
bitmap += bitValue;
}
bitValue *= 2;
if (bitValue === 256) {
packet.writeInt8(bitmap);
bitmap = 0;
bitValue = 1;
}
});
if (bitValue !== 1) {
packet.writeInt8(bitmap);
}
// TODO: explain meaning of the flag
// afaik, if set n*2 bytes with type of parameter are sent before parameters
// if not, previous execution types are used (TODO prooflink)
packet.writeInt8(1); // new-params-bound-flag
// Write parameter types
parameters.forEach(parameter => {
packet.writeInt8(parameter.type); // field type
packet.writeInt8(0); // parameter flag
});
// Write parameter values
parameters.forEach(parameter => {
if (parameter.type !== Types.NULL) {
parameter.writer.call(packet, parameter.value);
}
});
}
return packet;
}
}
module.exports = Execute;

112
node_modules/mysql2/lib/packets/handshake.js generated vendored Normal file
View File

@ -0,0 +1,112 @@
'use strict';
const Packet = require('../packets/packet');
const ClientConstants = require('../constants/client.js');
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
class Handshake {
constructor(args) {
this.protocolVersion = args.protocolVersion;
this.serverVersion = args.serverVersion;
this.capabilityFlags = args.capabilityFlags;
this.connectionId = args.connectionId;
this.authPluginData1 = args.authPluginData1;
this.authPluginData2 = args.authPluginData2;
this.characterSet = args.characterSet;
this.statusFlags = args.statusFlags;
this.autPluginName = args.autPluginName;
}
setScrambleData(cb) {
require('crypto').randomBytes(20, (err, data) => {
if (err) {
cb(err);
return;
}
this.authPluginData1 = data.slice(0, 8);
this.authPluginData2 = data.slice(8, 20);
cb();
});
}
toPacket(sequenceId) {
const length = 68 + Buffer.byteLength(this.serverVersion, 'utf8');
const buffer = Buffer.alloc(length + 4, 0); // zero fill, 10 bytes filler later needs to contain zeros
const packet = new Packet(sequenceId, buffer, 0, length + 4);
packet.offset = 4;
packet.writeInt8(this.protocolVersion);
packet.writeString(this.serverVersion, 'cesu8');
packet.writeInt8(0);
packet.writeInt32(this.connectionId);
packet.writeBuffer(this.authPluginData1);
packet.writeInt8(0);
const capabilityFlagsBuffer = Buffer.allocUnsafe(4);
capabilityFlagsBuffer.writeUInt32LE(this.capabilityFlags, 0);
packet.writeBuffer(capabilityFlagsBuffer.slice(0, 2));
packet.writeInt8(this.characterSet);
packet.writeInt16(this.statusFlags);
packet.writeBuffer(capabilityFlagsBuffer.slice(2, 4));
packet.writeInt8(21); // authPluginDataLength
packet.skip(10);
packet.writeBuffer(this.authPluginData2);
packet.writeInt8(0);
packet.writeString('mysql_native_password', 'latin1');
packet.writeInt8(0);
return packet;
}
static fromPacket(packet) {
const args = {};
args.protocolVersion = packet.readInt8();
args.serverVersion = packet.readNullTerminatedString('cesu8');
args.connectionId = packet.readInt32();
args.authPluginData1 = packet.readBuffer(8);
packet.skip(1);
const capabilityFlagsBuffer = Buffer.allocUnsafe(4);
capabilityFlagsBuffer[0] = packet.readInt8();
capabilityFlagsBuffer[1] = packet.readInt8();
if (packet.haveMoreData()) {
args.characterSet = packet.readInt8();
args.statusFlags = packet.readInt16();
// upper 2 bytes
capabilityFlagsBuffer[2] = packet.readInt8();
capabilityFlagsBuffer[3] = packet.readInt8();
args.capabilityFlags = capabilityFlagsBuffer.readUInt32LE(0);
if (args.capabilityFlags & ClientConstants.PLUGIN_AUTH) {
args.authPluginDataLength = packet.readInt8();
} else {
args.authPluginDataLength = 0;
packet.skip(1);
}
packet.skip(10);
} else {
args.capabilityFlags = capabilityFlagsBuffer.readUInt16LE(0);
}
const isSecureConnection =
args.capabilityFlags & ClientConstants.SECURE_CONNECTION;
if (isSecureConnection) {
const authPluginDataLength = args.authPluginDataLength;
if (authPluginDataLength === 0) {
// for Secure Password Authentication
args.authPluginDataLength = 20;
args.authPluginData2 = packet.readBuffer(12);
packet.skip(1);
} else {
// length > 0
// for Custom Auth Plugin (PLUGIN_AUTH)
const len = Math.max(13, authPluginDataLength - 8);
args.authPluginData2 = packet.readBuffer(len);
}
}
if (args.capabilityFlags & ClientConstants.PLUGIN_AUTH) {
args.autPluginName = packet.readNullTerminatedString('ascii');
}
return new Handshake(args);
}
}
module.exports = Handshake;

145
node_modules/mysql2/lib/packets/handshake_response.js generated vendored Normal file
View File

@ -0,0 +1,145 @@
'use strict';
const ClientConstants = require('../constants/client.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const Packet = require('../packets/packet.js');
const auth41 = require('../auth_41.js');
class HandshakeResponse {
constructor(handshake) {
this.user = handshake.user || '';
this.database = handshake.database || '';
this.password = handshake.password || '';
this.passwordSha1 = handshake.passwordSha1;
this.authPluginData1 = handshake.authPluginData1;
this.authPluginData2 = handshake.authPluginData2;
this.compress = handshake.compress;
this.clientFlags = handshake.flags;
// TODO: pre-4.1 auth support
let authToken;
if (this.passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
this.passwordSha1,
this.authPluginData1,
this.authPluginData2
);
} else {
authToken = auth41.calculateToken(
this.password,
this.authPluginData1,
this.authPluginData2
);
}
this.authToken = authToken;
this.charsetNumber = handshake.charsetNumber;
this.encoding = CharsetToEncoding[handshake.charsetNumber];
this.connectAttributes = handshake.connectAttributes;
}
serializeResponse(buffer) {
const isSet = flag => this.clientFlags & ClientConstants[flag];
const packet = new Packet(0, buffer, 0, buffer.length);
packet.offset = 4;
packet.writeInt32(this.clientFlags);
packet.writeInt32(0); // max packet size. todo: move to config
packet.writeInt8(this.charsetNumber);
packet.skip(23);
const encoding = this.encoding;
packet.writeNullTerminatedString(this.user, encoding);
let k;
if (isSet('PLUGIN_AUTH_LENENC_CLIENT_DATA')) {
packet.writeLengthCodedNumber(this.authToken.length);
packet.writeBuffer(this.authToken);
} else if (isSet('SECURE_CONNECTION')) {
packet.writeInt8(this.authToken.length);
packet.writeBuffer(this.authToken);
} else {
packet.writeBuffer(this.authToken);
packet.writeInt8(0);
}
if (isSet('CONNECT_WITH_DB')) {
packet.writeNullTerminatedString(this.database, encoding);
}
if (isSet('PLUGIN_AUTH')) {
// TODO: pass from config
packet.writeNullTerminatedString('mysql_native_password', 'latin1');
}
if (isSet('CONNECT_ATTRS')) {
const connectAttributes = this.connectAttributes || {};
const attrNames = Object.keys(connectAttributes);
let keysLength = 0;
for (k = 0; k < attrNames.length; ++k) {
keysLength += Packet.lengthCodedStringLength(attrNames[k], encoding);
keysLength += Packet.lengthCodedStringLength(
connectAttributes[attrNames[k]],
encoding
);
}
packet.writeLengthCodedNumber(keysLength);
for (k = 0; k < attrNames.length; ++k) {
packet.writeLengthCodedString(attrNames[k], encoding);
packet.writeLengthCodedString(
connectAttributes[attrNames[k]],
encoding
);
}
}
return packet;
}
toPacket() {
if (typeof this.user !== 'string') {
throw new Error('"user" connection config property must be a string');
}
if (typeof this.database !== 'string') {
throw new Error('"database" connection config property must be a string');
}
// dry run: calculate resulting packet length
const p = this.serializeResponse(Packet.MockBuffer());
return this.serializeResponse(Buffer.alloc(p.offset));
}
static fromPacket(packet) {
const args = {};
args.clientFlags = packet.readInt32();
function isSet(flag) {
return args.clientFlags & ClientConstants[flag];
}
args.maxPacketSize = packet.readInt32();
args.charsetNumber = packet.readInt8();
const encoding = CharsetToEncoding[args.charsetNumber];
args.encoding = encoding;
packet.skip(23);
args.user = packet.readNullTerminatedString(encoding);
let authTokenLength;
if (isSet('PLUGIN_AUTH_LENENC_CLIENT_DATA')) {
authTokenLength = packet.readLengthCodedNumber(encoding);
args.authToken = packet.readBuffer(authTokenLength);
} else if (isSet('SECURE_CONNECTION')) {
authTokenLength = packet.readInt8();
args.authToken = packet.readBuffer(authTokenLength);
} else {
args.authToken = packet.readNullTerminatedString(encoding);
}
if (isSet('CONNECT_WITH_DB')) {
args.database = packet.readNullTerminatedString(encoding);
}
if (isSet('PLUGIN_AUTH')) {
args.authPluginName = packet.readNullTerminatedString(encoding);
}
if (isSet('CONNECT_ATTRS')) {
const keysLength = packet.readLengthCodedNumber(encoding);
const keysEnd = packet.offset + keysLength;
const attrs = {};
while (packet.offset < keysEnd) {
attrs[
packet.readLengthCodedString(encoding)
] = packet.readLengthCodedString(encoding);
}
args.connectAttributes = attrs;
}
return args;
}
}
module.exports = HandshakeResponse;

127
node_modules/mysql2/lib/packets/index.js generated vendored Normal file
View File

@ -0,0 +1,127 @@
'use strict';
const process = require('process');
const AuthSwitchRequest = require('./auth_switch_request');
const AuthSwitchRequestMoreData = require('./auth_switch_request_more_data');
const AuthSwitchResponse = require('./auth_switch_response');
const BinaryRow = require('./binary_row');
const BinlogDump = require('./binlog_dump');
const ChangeUser = require('./change_user');
const CloseStatement = require('./close_statement');
const ColumnDefinition = require('./column_definition');
const Execute = require('./execute');
const Handshake = require('./handshake');
const HandshakeResponse = require('./handshake_response');
const PrepareStatement = require('./prepare_statement');
const PreparedStatementHeader = require('./prepared_statement_header');
const Query = require('./query');
const RegisterSlave = require('./register_slave');
const ResultSetHeader = require('./resultset_header');
const SSLRequest = require('./ssl_request');
const TextRow = require('./text_row');
const ctorMap = {
AuthSwitchRequest,
AuthSwitchRequestMoreData,
AuthSwitchResponse,
BinaryRow,
BinlogDump,
ChangeUser,
CloseStatement,
ColumnDefinition,
Execute,
Handshake,
HandshakeResponse,
PrepareStatement,
PreparedStatementHeader,
Query,
RegisterSlave,
ResultSetHeader,
SSLRequest,
TextRow
};
Object.entries(ctorMap).forEach(([name, ctor]) => {
module.exports[name] = ctor;
// monkey-patch it to include name if debug is on
if (process.env.NODE_DEBUG) {
if (ctor.prototype.toPacket) {
const old = ctor.prototype.toPacket;
ctor.prototype.toPacket = function() {
const p = old.call(this);
p._name = name;
return p;
};
}
}
});
// simple packets:
const Packet = require('./packet');
exports.Packet = Packet;
class OK {
static toPacket(args, encoding) {
args = args || {};
const affectedRows = args.affectedRows || 0;
const insertId = args.insertId || 0;
const serverStatus = args.serverStatus || 0;
const warningCount = args.warningCount || 0;
const message = args.message || '';
let length = 9 + Packet.lengthCodedNumberLength(affectedRows);
length += Packet.lengthCodedNumberLength(insertId);
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(0);
packet.writeLengthCodedNumber(affectedRows);
packet.writeLengthCodedNumber(insertId);
packet.writeInt16(serverStatus);
packet.writeInt16(warningCount);
packet.writeString(message, encoding);
packet._name = 'OK';
return packet;
}
}
exports.OK = OK;
// warnings, statusFlags
class EOF {
static toPacket(warnings, statusFlags) {
if (typeof warnings === 'undefined') {
warnings = 0;
}
if (typeof statusFlags === 'undefined') {
statusFlags = 0;
}
const packet = new Packet(0, Buffer.allocUnsafe(9), 0, 9);
packet.offset = 4;
packet.writeInt8(0xfe);
packet.writeInt16(warnings);
packet.writeInt16(statusFlags);
packet._name = 'EOF';
return packet;
}
}
exports.EOF = EOF;
class Error {
static toPacket(args, encoding) {
const length = 13 + Buffer.byteLength(args.message, 'utf8');
const packet = new Packet(0, Buffer.allocUnsafe(length), 0, length);
packet.offset = 4;
packet.writeInt8(0xff);
packet.writeInt16(args.code);
// TODO: sql state parameter
packet.writeString('#_____', encoding);
packet.writeString(args.message, encoding);
packet._name = 'Error';
return packet;
}
}
exports.Error = Error;

903
node_modules/mysql2/lib/packets/packet.js generated vendored Normal file
View File

@ -0,0 +1,903 @@
'use strict';
const ErrorCodeToName = require('../constants/errors.js');
const NativeBuffer = require('buffer').Buffer;
const Long = require('long');
const StringParser = require('../parsers/string.js');
const INVALID_DATE = new Date(NaN);
// this is nearly duplicate of previous function so generated code is not slower
// due to "if (dateStrings)" branching
const pad = '000000000000';
function leftPad(num, value) {
const s = value.toString();
// if we don't need to pad
if (s.length >= num) {
return s;
}
return (pad + s).slice(-num);
}
// The whole reason parse* function below exist
// is because String creation is relatively expensive (at least with V8), and if we have
// a buffer with "12345" content ideally we would like to bypass intermediate
// "12345" string creation and directly build 12345 number out of
// <Buffer 31 32 33 34 35> data.
// In my benchmarks the difference is ~25M 8-digit numbers per second vs
// 4.5 M using Number(packet.readLengthCodedString())
// not used when size is close to max precision as series of *10 accumulate error
// and approximate result mihgt be diffreent from (approximate as well) Number(bigNumStringValue))
// In the futire node version if speed difference is smaller parse* functions might be removed
// don't consider them as Packet public API
const minus = '-'.charCodeAt(0);
const plus = '+'.charCodeAt(0);
// TODO: handle E notation
const dot = '.'.charCodeAt(0);
const exponent = 'e'.charCodeAt(0);
const exponentCapital = 'E'.charCodeAt(0);
class Packet {
constructor(id, buffer, start, end) {
// hot path, enable checks when testing only
// if (!Buffer.isBuffer(buffer) || typeof start == 'undefined' || typeof end == 'undefined')
// throw new Error('invalid packet');
this.sequenceId = id;
this.numPackets = 1;
this.buffer = buffer;
this.start = start;
this.offset = start + 4;
this.end = end;
}
// ==============================
// readers
// ==============================
reset() {
this.offset = this.start + 4;
}
length() {
return this.end - this.start;
}
slice() {
return this.buffer.slice(this.start, this.end);
}
dump() {
// eslint-disable-next-line no-console
console.log(
[this.buffer.asciiSlice(this.start, this.end)],
this.buffer.slice(this.start, this.end),
this.length(),
this.sequenceId
);
}
haveMoreData() {
return this.end > this.offset;
}
skip(num) {
this.offset += num;
}
readInt8() {
return this.buffer[this.offset++];
}
readInt16() {
this.offset += 2;
return this.buffer.readUInt16LE(this.offset - 2);
}
readInt24() {
return this.readInt16() + (this.readInt8() << 16);
}
readInt32() {
this.offset += 4;
return this.buffer.readUInt32LE(this.offset - 4);
}
readSInt8() {
return this.buffer.readInt8(this.offset++);
}
readSInt16() {
this.offset += 2;
return this.buffer.readInt16LE(this.offset - 2);
}
readSInt32() {
this.offset += 4;
return this.buffer.readInt32LE(this.offset - 4);
}
readInt64JSNumber() {
const word0 = this.readInt32();
const word1 = this.readInt32();
const l = new Long(word0, word1, true);
return l.toNumber();
}
readSInt64JSNumber() {
const word0 = this.readInt32();
const word1 = this.readInt32();
if (!(word1 & 0x80000000)) {
return word0 + 0x100000000 * word1;
}
const l = new Long(word0, word1, false);
return l.toNumber();
}
readInt64String() {
const word0 = this.readInt32();
const word1 = this.readInt32();
const res = new Long(word0, word1, true);
return res.toString();
}
readSInt64String() {
const word0 = this.readInt32();
const word1 = this.readInt32();
const res = new Long(word0, word1, false);
return res.toString();
}
readInt64() {
const word0 = this.readInt32();
const word1 = this.readInt32();
let res = new Long(word0, word1, true);
const resNumber = res.toNumber();
const resString = res.toString();
res = resNumber.toString() === resString ? resNumber : resString;
return res;
}
readSInt64() {
const word0 = this.readInt32();
const word1 = this.readInt32();
let res = new Long(word0, word1, false);
const resNumber = res.toNumber();
const resString = res.toString();
res = resNumber.toString() === resString ? resNumber : resString;
return res;
}
isEOF() {
return this.buffer[this.offset] === 0xfe && this.length() < 13;
}
eofStatusFlags() {
return this.buffer.readInt16LE(this.offset + 3);
}
eofWarningCount() {
return this.buffer.readInt16LE(this.offset + 1);
}
readLengthCodedNumber(bigNumberStrings, signed) {
const byte1 = this.buffer[this.offset++];
if (byte1 < 251) {
return byte1;
}
return this.readLengthCodedNumberExt(byte1, bigNumberStrings, signed);
}
readLengthCodedNumberSigned(bigNumberStrings) {
return this.readLengthCodedNumber(bigNumberStrings, true);
}
readLengthCodedNumberExt(tag, bigNumberStrings, signed) {
let word0, word1;
let res;
if (tag === 0xfb) {
return null;
}
if (tag === 0xfc) {
return this.readInt8() + (this.readInt8() << 8);
}
if (tag === 0xfd) {
return this.readInt8() + (this.readInt8() << 8) + (this.readInt8() << 16);
}
if (tag === 0xfe) {
// TODO: check version
// Up to MySQL 3.22, 0xfe was followed by a 4-byte integer.
word0 = this.readInt32();
word1 = this.readInt32();
if (word1 === 0) {
return word0; // don't convert to float if possible
}
if (word1 < 2097152) {
// max exact float point int, 2^52 / 2^32
return word1 * 0x100000000 + word0;
}
res = new Long(word0, word1, !signed); // Long need unsigned
const resNumber = res.toNumber();
const resString = res.toString();
res = resNumber.toString() === resString ? resNumber : resString;
return bigNumberStrings ? resString : res;
}
// eslint-disable-next-line no-console
console.trace();
throw new Error(`Should not reach here: ${tag}`);
}
readFloat() {
const res = this.buffer.readFloatLE(this.offset);
this.offset += 4;
return res;
}
readDouble() {
const res = this.buffer.readDoubleLE(this.offset);
this.offset += 8;
return res;
}
readBuffer(len) {
if (typeof len === 'undefined') {
len = this.end - this.offset;
}
this.offset += len;
return this.buffer.slice(this.offset - len, this.offset);
}
// DATE, DATETIME and TIMESTAMP
readDateTime(timezone) {
if (!timezone || timezone === 'Z' || timezone === 'local') {
const length = this.readInt8();
if (length === 0xfb) {
return null;
}
let y = 0;
let m = 0;
let d = 0;
let H = 0;
let M = 0;
let S = 0;
let ms = 0;
if (length > 3) {
y = this.readInt16();
m = this.readInt8();
d = this.readInt8();
}
if (length > 6) {
H = this.readInt8();
M = this.readInt8();
S = this.readInt8();
}
if (length > 10) {
ms = this.readInt32() / 1000;
}
if (y + m + d + H + M + S + ms === 0) {
return INVALID_DATE;
}
if (timezone === 'Z') {
return new Date(Date.UTC(y, m - 1, d, H, M, S, ms));
}
return new Date(y, m - 1, d, H, M, S, ms);
}
let str = this.readDateTimeString(6, 'T');
if (str.length === 10) {
str += 'T00:00:00';
}
return new Date(str + timezone);
}
readDateTimeString(decimals, timeSep) {
const length = this.readInt8();
let y = 0;
let m = 0;
let d = 0;
let H = 0;
let M = 0;
let S = 0;
let ms = 0;
let str;
if (length > 3) {
y = this.readInt16();
m = this.readInt8();
d = this.readInt8();
str = [leftPad(4, y), leftPad(2, m), leftPad(2, d)].join('-');
}
if (length > 6) {
H = this.readInt8();
M = this.readInt8();
S = this.readInt8();
str += `${timeSep || ' '}${[
leftPad(2, H),
leftPad(2, M),
leftPad(2, S)
].join(':')}`;
}
if (length > 10) {
ms = this.readInt32();
str += '.';
if (decimals) {
ms = leftPad(6, ms);
if (ms.length > decimals) {
ms = ms.substring(0, decimals); // rounding is done at the MySQL side, only 0 are here
}
}
str += ms;
}
return str;
}
// TIME - value as a string, Can be negative
readTimeString(convertTtoMs) {
const length = this.readInt8();
if (length === 0) {
return '00:00:00';
}
const sign = this.readInt8() ? -1 : 1; // 'isNegative' flag byte
let d = 0;
let H = 0;
let M = 0;
let S = 0;
let ms = 0;
if (length > 6) {
d = this.readInt32();
H = this.readInt8();
M = this.readInt8();
S = this.readInt8();
}
if (length > 10) {
ms = this.readInt32();
}
if (convertTtoMs) {
H += d * 24;
M += H * 60;
S += M * 60;
ms += S * 1000;
ms *= sign;
return ms;
}
return (
(sign === -1 ? '-' : '') +
[d ? d * 24 + H : H, leftPad(2, M), leftPad(2, S)].join(':') +
(ms ? `.${ms}` : '')
);
}
readLengthCodedString(encoding) {
const len = this.readLengthCodedNumber();
// TODO: check manually first byte here to avoid polymorphic return type?
if (len === null) {
return null;
}
this.offset += len;
// TODO: Use characterSetCode to get proper encoding
// https://github.com/sidorares/node-mysql2/pull/374
return StringParser.decode(
this.buffer.slice(this.offset - len, this.offset),
encoding
);
}
readLengthCodedBuffer() {
const len = this.readLengthCodedNumber();
if (len === null) {
return null;
}
return this.readBuffer(len);
}
readNullTerminatedString(encoding) {
const start = this.offset;
let end = this.offset;
while (this.buffer[end]) {
end = end + 1; // TODO: handle OOB check
}
this.offset = end + 1;
return StringParser.decode(this.buffer.slice(start, end), encoding);
}
// TODO reuse?
readString(len, encoding) {
if ((typeof len === 'string') && (typeof encoding === 'undefined')) {
encoding = len
len = undefined
}
if (typeof len === 'undefined') {
len = this.end - this.offset;
}
this.offset += len;
return StringParser.decode(
this.buffer.slice(this.offset - len, this.offset),
encoding
);
}
parseInt(len, supportBigNumbers) {
if (len === null) {
return null;
}
if (len >= 14 && !supportBigNumbers) {
const s = this.buffer.toString('ascii', this.offset, this.offset + len);
this.offset += len;
return Number(s);
}
let result = 0;
const start = this.offset;
const end = this.offset + len;
let sign = 1;
if (len === 0) {
return 0; // TODO: assert? exception?
}
if (this.buffer[this.offset] === minus) {
this.offset++;
sign = -1;
}
// max precise int is 9007199254740992
let str;
const numDigits = end - this.offset;
if (supportBigNumbers) {
if (numDigits >= 15) {
str = this.readString(end - this.offset, 'binary');
result = parseInt(str, 10);
if (result.toString() === str) {
return sign * result;
}
return sign === -1 ? `-${str}` : str;
}
if (numDigits > 16) {
str = this.readString(end - this.offset);
return sign === -1 ? `-${str}` : str;
}
}
if (this.buffer[this.offset] === plus) {
this.offset++; // just ignore
}
while (this.offset < end) {
result *= 10;
result += this.buffer[this.offset] - 48;
this.offset++;
}
const num = result * sign;
if (!supportBigNumbers) {
return num;
}
str = this.buffer.toString('ascii', start, end);
if (num.toString() === str) {
return num;
}
return str;
}
// note that if value of inputNumberAsString is bigger than MAX_SAFE_INTEGER
// ( or smaller than MIN_SAFE_INTEGER ) the parseIntNoBigCheck result might be
// different from what you would get from Number(inputNumberAsString)
// String(parseIntNoBigCheck) <> String(Number(inputNumberAsString)) <> inputNumberAsString
parseIntNoBigCheck(len) {
if (len === null) {
return null;
}
let result = 0;
const end = this.offset + len;
let sign = 1;
if (len === 0) {
return 0; // TODO: assert? exception?
}
if (this.buffer[this.offset] === minus) {
this.offset++;
sign = -1;
}
if (this.buffer[this.offset] === plus) {
this.offset++; // just ignore
}
while (this.offset < end) {
result *= 10;
result += this.buffer[this.offset] - 48;
this.offset++;
}
return result * sign;
}
// copy-paste from https://github.com/mysqljs/mysql/blob/master/lib/protocol/Parser.js
parseGeometryValue() {
const buffer = this.readLengthCodedBuffer();
let offset = 4;
if (buffer === null || !buffer.length) {
return null;
}
function parseGeometry() {
let x, y, i, j, numPoints, line;
let result = null;
const byteOrder = buffer.readUInt8(offset);
offset += 1;
const wkbType = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
switch (wkbType) {
case 1: // WKBPoint
x = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
y = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
result = { x: x, y: y };
break;
case 2: // WKBLineString
numPoints = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
result = [];
for (i = numPoints; i > 0; i--) {
x = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
y = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
result.push({ x: x, y: y });
}
break;
case 3: // WKBPolygon
// eslint-disable-next-line no-case-declarations
const numRings = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
result = [];
for (i = numRings; i > 0; i--) {
numPoints = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
line = [];
for (j = numPoints; j > 0; j--) {
x = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
y = byteOrder
? buffer.readDoubleLE(offset)
: buffer.readDoubleBE(offset);
offset += 8;
line.push({ x: x, y: y });
}
result.push(line);
}
break;
case 4: // WKBMultiPoint
case 5: // WKBMultiLineString
case 6: // WKBMultiPolygon
case 7: // WKBGeometryCollection
// eslint-disable-next-line no-case-declarations
const num = byteOrder
? buffer.readUInt32LE(offset)
: buffer.readUInt32BE(offset);
offset += 4;
result = [];
for (i = num; i > 0; i--) {
result.push(parseGeometry());
}
break;
}
return result;
}
return parseGeometry();
}
parseDate(timezone) {
const strLen = this.readLengthCodedNumber();
if (strLen === null) {
return null;
}
if (strLen !== 10) {
// we expect only YYYY-MM-DD here.
// if for some reason it's not the case return invalid date
return new Date(NaN);
}
const y = this.parseInt(4);
this.offset++; // -
const m = this.parseInt(2);
this.offset++; // -
const d = this.parseInt(2);
if (!timezone || timezone === 'local') {
return new Date(y, m - 1, d);
}
if (timezone === 'Z') {
return new Date(Date.UTC(y, m - 1, d));
}
return new Date(
`${leftPad(4, y)}-${leftPad(2, m)}-${leftPad(2, d)}T00:00:00${timezone}`
);
}
parseDateTime(timezone) {
const str = this.readLengthCodedString('binary');
if (str === null) {
return null;
}
if (!timezone || timezone === 'local') {
return new Date(str);
}
return new Date(`${str}${timezone}`);
}
parseFloat(len) {
if (len === null) {
return null;
}
let result = 0;
const end = this.offset + len;
let factor = 1;
let pastDot = false;
let charCode = 0;
if (len === 0) {
return 0; // TODO: assert? exception?
}
if (this.buffer[this.offset] === minus) {
this.offset++;
factor = -1;
}
if (this.buffer[this.offset] === plus) {
this.offset++; // just ignore
}
while (this.offset < end) {
charCode = this.buffer[this.offset];
if (charCode === dot) {
pastDot = true;
this.offset++;
} else if (charCode === exponent || charCode === exponentCapital) {
this.offset++;
const exponentValue = this.parseInt(end - this.offset);
return (result / factor) * Math.pow(10, exponentValue);
} else {
result *= 10;
result += this.buffer[this.offset] - 48;
this.offset++;
if (pastDot) {
factor = factor * 10;
}
}
}
return result / factor;
}
parseLengthCodedIntNoBigCheck() {
return this.parseIntNoBigCheck(this.readLengthCodedNumber());
}
parseLengthCodedInt(supportBigNumbers) {
return this.parseInt(this.readLengthCodedNumber(), supportBigNumbers);
}
parseLengthCodedIntString() {
return this.readLengthCodedString('binary');
}
parseLengthCodedFloat() {
return this.parseFloat(this.readLengthCodedNumber());
}
peekByte() {
return this.buffer[this.offset];
}
// OxFE is often used as "Alt" flag - not ok, not error.
// For example, it's first byte of AuthSwitchRequest
isAlt() {
return this.peekByte() === 0xfe;
}
isError() {
return this.peekByte() === 0xff;
}
asError(encoding) {
this.reset();
this.readInt8(); // fieldCount
const errorCode = this.readInt16();
let sqlState = '';
if (this.buffer[this.offset] === 0x23) {
this.skip(1);
sqlState = this.readBuffer(5).toString();
}
const message = this.readString(undefined, encoding);
const err = new Error(message);
err.code = ErrorCodeToName[errorCode];
err.errno = errorCode;
err.sqlState = sqlState;
err.sqlMessage = message;
return err;
}
writeInt32(n) {
this.buffer.writeUInt32LE(n, this.offset);
this.offset += 4;
}
writeInt24(n) {
this.writeInt8(n & 0xff);
this.writeInt16(n >> 8);
}
writeInt16(n) {
this.buffer.writeUInt16LE(n, this.offset);
this.offset += 2;
}
writeInt8(n) {
this.buffer.writeUInt8(n, this.offset);
this.offset++;
}
writeDouble(n) {
this.buffer.writeDoubleLE(n, this.offset);
this.offset += 8;
}
writeBuffer(b) {
b.copy(this.buffer, this.offset);
this.offset += b.length;
}
writeNull() {
this.buffer[this.offset] = 0xfb;
this.offset++;
}
// TODO: refactor following three?
writeNullTerminatedString(s, encoding) {
const buf = StringParser.encode(s, encoding);
this.buffer.length && buf.copy(this.buffer, this.offset);
this.offset += buf.length;
this.writeInt8(0);
}
writeString(s, encoding) {
if (s === null) {
this.writeInt8(0xfb);
return;
}
if (s.length === 0) {
return;
}
// const bytes = Buffer.byteLength(s, 'utf8');
// this.buffer.write(s, this.offset, bytes, 'utf8');
// this.offset += bytes;
const buf = StringParser.encode(s, encoding);
this.buffer.length && buf.copy(this.buffer, this.offset);
this.offset += buf.length;
}
writeLengthCodedString(s, encoding) {
const buf = StringParser.encode(s, encoding);
this.writeLengthCodedNumber(buf.length);
this.buffer.length && buf.copy(this.buffer, this.offset);
this.offset += buf.length;
}
writeLengthCodedBuffer(b) {
this.writeLengthCodedNumber(b.length);
b.copy(this.buffer, this.offset);
this.offset += b.length;
}
writeLengthCodedNumber(n) {
if (n < 0xfb) {
return this.writeInt8(n);
}
if (n < 0xffff) {
this.writeInt8(0xfc);
return this.writeInt16(n);
}
if (n < 0xffffff) {
this.writeInt8(0xfd);
return this.writeInt24(n);
}
if (n === null) {
return this.writeInt8(0xfb);
}
// TODO: check that n is out of int precision
this.writeInt8(0xfe);
this.buffer.writeUInt32LE(n, this.offset);
this.offset += 4;
this.buffer.writeUInt32LE(n >> 32, this.offset);
this.offset += 4;
return this.offset;
}
writeDate(d, timezone) {
this.buffer.writeUInt8(11, this.offset);
if (!timezone || timezone === 'local') {
this.buffer.writeUInt16LE(d.getFullYear(), this.offset + 1);
this.buffer.writeUInt8(d.getMonth() + 1, this.offset + 3);
this.buffer.writeUInt8(d.getDate(), this.offset + 4);
this.buffer.writeUInt8(d.getHours(), this.offset + 5);
this.buffer.writeUInt8(d.getMinutes(), this.offset + 6);
this.buffer.writeUInt8(d.getSeconds(), this.offset + 7);
this.buffer.writeUInt32LE(d.getMilliseconds() * 1000, this.offset + 8);
} else {
if (timezone !== 'Z') {
const offset =
(timezone[0] === '-' ? -1 : 1) *
(parseInt(timezone.substring(1, 3), 10) * 60 +
parseInt(timezone.substring(4), 10));
if (offset !== 0) {
d = new Date(d.getTime() + 60000 * offset);
}
}
this.buffer.writeUInt16LE(d.getUTCFullYear(), this.offset + 1);
this.buffer.writeUInt8(d.getUTCMonth() + 1, this.offset + 3);
this.buffer.writeUInt8(d.getUTCDate(), this.offset + 4);
this.buffer.writeUInt8(d.getUTCHours(), this.offset + 5);
this.buffer.writeUInt8(d.getUTCMinutes(), this.offset + 6);
this.buffer.writeUInt8(d.getUTCSeconds(), this.offset + 7);
this.buffer.writeUInt32LE(d.getUTCMilliseconds() * 1000, this.offset + 8);
}
this.offset += 12;
}
writeHeader(sequenceId) {
const offset = this.offset;
this.offset = 0;
this.writeInt24(this.buffer.length - 4);
this.writeInt8(sequenceId);
this.offset = offset;
}
clone() {
return new Packet(this.sequenceId, this.buffer, this.start, this.end);
}
type() {
if (this.isEOF()) {
return 'EOF';
}
if (this.isError()) {
return 'Error';
}
if (this.buffer[this.offset] === 0) {
return 'maybeOK'; // could be other packet types as well
}
return '';
}
static lengthCodedNumberLength(n) {
if (n < 0xfb) {
return 1;
}
if (n < 0xffff) {
return 3;
}
if (n < 0xffffff) {
return 5;
}
return 9;
}
static lengthCodedStringLength(str, encoding) {
const buf = StringParser.encode(str, encoding);
const slen = buf.length;
return Packet.lengthCodedNumberLength(slen) + slen;
}
static MockBuffer() {
const noop = function() {};
const res = Buffer.alloc(0);
for (const op in NativeBuffer.prototype) {
if (typeof res[op] === 'function') {
res[op] = noop;
}
}
return res;
}
}
module.exports = Packet;

27
node_modules/mysql2/lib/packets/prepare_statement.js generated vendored Normal file
View File

@ -0,0 +1,27 @@
'use strict';
const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');
const StringParser = require('../parsers/string.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
class PrepareStatement {
constructor(sql, charsetNumber) {
this.query = sql;
this.charsetNumber = charsetNumber;
this.encoding = CharsetToEncoding[charsetNumber];
}
toPacket() {
const buf = StringParser.encode(this.query, this.encoding);
const length = 5 + buf.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.STMT_PREPARE);
packet.writeBuffer(buf);
return packet;
}
}
module.exports = PrepareStatement;

View File

@ -0,0 +1,16 @@
'use strict';
class PreparedStatementHeader {
constructor(packet) {
packet.skip(1); // should be 0
this.id = packet.readInt32();
this.fieldCount = packet.readInt16();
this.parameterCount = packet.readInt16();
packet.skip(1); // should be 0
this.warningCount = packet.readInt16();
}
}
// TODO: toPacket
module.exports = PreparedStatementHeader;

27
node_modules/mysql2/lib/packets/query.js generated vendored Normal file
View File

@ -0,0 +1,27 @@
'use strict';
const Packet = require('../packets/packet.js');
const CommandCode = require('../constants/commands.js');
const StringParser = require('../parsers/string.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
class Query {
constructor(sql, charsetNumber) {
this.query = sql;
this.charsetNumber = charsetNumber;
this.encoding = CharsetToEncoding[charsetNumber];
}
toPacket() {
const buf = StringParser.encode(this.query, this.encoding);
const length = 5 + buf.length;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCode.QUERY);
packet.writeBuffer(buf);
return packet;
}
}
module.exports = Query;

46
node_modules/mysql2/lib/packets/register_slave.js generated vendored Normal file
View File

@ -0,0 +1,46 @@
'use strict';
// http://dev.mysql.com/doc/internals/en/com-register-slave.html
// note that documentation is incorrect, for example command code is actually 0x15 but documented as 0x14
const Packet = require('../packets/packet');
const CommandCodes = require('../constants/commands');
class RegisterSlave {
constructor(opts) {
this.serverId = opts.serverId || 0;
this.slaveHostname = opts.slaveHostname || '';
this.slaveUser = opts.slaveUser || '';
this.slavePassword = opts.slavePassword || '';
this.slavePort = opts.slavePort || 0;
this.replicationRank = opts.replicationRank || 0;
this.masterId = opts.masterId || 0;
}
toPacket() {
const length =
15 + // TODO: should be ascii?
Buffer.byteLength(this.slaveHostname, 'utf8') +
Buffer.byteLength(this.slaveUser, 'utf8') +
Buffer.byteLength(this.slavePassword, 'utf8') +
3 +
4;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeInt8(CommandCodes.REGISTER_SLAVE);
packet.writeInt32(this.serverId);
packet.writeInt8(Buffer.byteLength(this.slaveHostname, 'utf8'));
packet.writeString(this.slaveHostname);
packet.writeInt8(Buffer.byteLength(this.slaveUser, 'utf8'));
packet.writeString(this.slaveUser);
packet.writeInt8(Buffer.byteLength(this.slavePassword, 'utf8'));
packet.writeString(this.slavePassword);
packet.writeInt16(this.slavePort);
packet.writeInt32(this.replicationRank);
packet.writeInt32(this.masterId);
return packet;
}
}
module.exports = RegisterSlave;

110
node_modules/mysql2/lib/packets/resultset_header.js generated vendored Normal file
View File

@ -0,0 +1,110 @@
'use strict';
// TODO: rename to OK packet
// https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
const Packet = require('./packet.js');
const ClientConstants = require('../constants/client.js');
const ServerSatusFlags = require('../constants/server_status.js');
const EncodingToCharset = require('../constants/encoding_charset.js');
const sessionInfoTypes = require('../constants/session_track.js');
class ResultSetHeader {
constructor(packet, connection) {
const bigNumberStrings = connection.config.bigNumberStrings;
const encoding = connection.serverEncoding;
const flags = connection._handshakePacket.capabilityFlags;
const isSet = function(flag) {
return flags & ClientConstants[flag];
};
if (packet.buffer[packet.offset] !== 0) {
this.fieldCount = packet.readLengthCodedNumber();
if (this.fieldCount === null) {
this.infileName = packet.readString(undefined, encoding);
}
return;
}
this.fieldCount = packet.readInt8(); // skip OK byte
this.affectedRows = packet.readLengthCodedNumber(bigNumberStrings);
this.insertId = packet.readLengthCodedNumberSigned(bigNumberStrings);
this.info = '';
if (isSet('PROTOCOL_41')) {
this.serverStatus = packet.readInt16();
this.warningStatus = packet.readInt16();
} else if (isSet('TRANSACTIONS')) {
this.serverStatus = packet.readInt16();
}
let stateChanges = null;
if (isSet('SESSION_TRACK') && packet.offset < packet.end) {
this.info = packet.readLengthCodedString(encoding);
if (this.serverStatus && ServerSatusFlags.SERVER_SESSION_STATE_CHANGED) {
// session change info record - see
// https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html#cs-sect-packet-ok-sessioninfo
let len =
packet.offset < packet.end ? packet.readLengthCodedNumber() : 0;
const end = packet.offset + len;
let type, key, stateEnd;
if (len > 0) {
stateChanges = {
systemVariables: {},
schema: null,
trackStateChange: null
};
}
while (packet.offset < end) {
type = packet.readInt8();
len = packet.readLengthCodedNumber();
stateEnd = packet.offset + len;
if (type === sessionInfoTypes.SYSTEM_VARIABLES) {
key = packet.readLengthCodedString(encoding);
const val = packet.readLengthCodedString(encoding);
stateChanges.systemVariables[key] = val;
if (key === 'character_set_client') {
const charsetNumber = EncodingToCharset[val];
connection.config.charsetNumber = charsetNumber;
}
} else if (type === sessionInfoTypes.SCHEMA) {
key = packet.readLengthCodedString(encoding);
stateChanges.schema = key;
} else if (type === sessionInfoTypes.STATE_CHANGE) {
stateChanges.trackStateChange = packet.readLengthCodedString(
encoding
);
} else {
// unsupported session track type. For now just ignore
}
packet.offset = stateEnd;
}
}
} else {
this.info = packet.readString(undefined, encoding);
}
if (stateChanges) {
this.stateChanges = stateChanges;
}
const m = this.info.match(/\schanged:\s*(\d+)/i);
if (m !== null) {
this.changedRows = parseInt(m[1], 10);
}
}
// TODO: should be consistent instance member, but it's just easier here to have just function
static toPacket(fieldCount, insertId) {
let length = 4 + Packet.lengthCodedNumberLength(fieldCount);
if (typeof insertId !== 'undefined') {
length += Packet.lengthCodedNumberLength(insertId);
}
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
packet.offset = 4;
packet.writeLengthCodedNumber(fieldCount);
if (typeof insertId !== 'undefined') {
packet.writeLengthCodedNumber(insertId);
}
return packet;
}
}
module.exports = ResultSetHeader;

25
node_modules/mysql2/lib/packets/ssl_request.js generated vendored Normal file
View File

@ -0,0 +1,25 @@
'use strict';
const ClientConstants = require('../constants/client');
const Packet = require('../packets/packet');
class SSLRequest {
constructor(flags, charset) {
this.clientFlags = flags | ClientConstants.SSL;
this.charset = charset;
}
toPacket() {
const length = 36;
const buffer = Buffer.allocUnsafe(length);
const packet = new Packet(0, buffer, 0, length);
buffer.fill(0);
packet.offset = 4;
packet.writeInt32(this.clientFlags);
packet.writeInt32(0); // max packet size. todo: move to config
packet.writeInt8(this.charset);
return packet;
}
}
module.exports = SSLRequest;

47
node_modules/mysql2/lib/packets/text_row.js generated vendored Normal file
View File

@ -0,0 +1,47 @@
'use strict';
const Packet = require('../packets/packet');
class TextRow {
constructor(columns) {
this.columns = columns || [];
}
static fromPacket(packet) {
// packet.reset(); // set offset to starting point?
const columns = [];
while (packet.haveMoreData()) {
columns.push(packet.readLengthCodedString());
}
return new TextRow(columns);
}
static toPacket(columns, encoding) {
const sequenceId = 0; // TODO remove, this is calculated now in connecton
let length = 0;
columns.forEach(val => {
if (val === null || typeof val === 'undefined') {
++length;
return;
}
length += Packet.lengthCodedStringLength(val.toString(10), encoding);
});
const buffer = Buffer.allocUnsafe(length + 4);
const packet = new Packet(sequenceId, buffer, 0, length + 4);
packet.offset = 4;
columns.forEach(val => {
if (val === null) {
packet.writeNull();
return;
}
if (typeof val === 'undefined') {
packet.writeInt8(0);
return;
}
packet.writeLengthCodedString(val.toString(10), encoding);
});
return packet;
}
}
module.exports = TextRow;

184
node_modules/mysql2/lib/parsers/binary_parser.js generated vendored Normal file
View File

@ -0,0 +1,184 @@
'use strict';
const FieldFlags = require('../constants/field_flags.js');
const Charsets = require('../constants/charsets.js');
const Types = require('../constants/types.js');
const helpers = require('../helpers');
const genFunc = require('generate-function');
const parserCache = require('./parser_cache.js');
const typeNames = [];
for (const t in Types) {
typeNames[Types[t]] = t;
}
function readCodeFor(field, config, options, fieldNum) {
const supportBigNumbers =
options.supportBigNumbers || config.supportBigNumbers;
const bigNumberStrings = options.bigNumberStrings || config.bigNumberStrings;
const timezone = options.timezone || config.timezone;
const dateStrings = options.dateStrings || config.dateStrings;
const unsigned = field.flags & FieldFlags.UNSIGNED;
switch (field.columnType) {
case Types.TINY:
return unsigned ? 'packet.readInt8();' : 'packet.readSInt8();';
case Types.SHORT:
return unsigned ? 'packet.readInt16();' : 'packet.readSInt16();';
case Types.LONG:
case Types.INT24: // in binary protocol int24 is encoded in 4 bytes int32
return unsigned ? 'packet.readInt32();' : 'packet.readSInt32();';
case Types.YEAR:
return 'packet.readInt16()';
case Types.FLOAT:
return 'packet.readFloat();';
case Types.DOUBLE:
return 'packet.readDouble();';
case Types.NULL:
return 'null;';
case Types.DATE:
case Types.DATETIME:
case Types.TIMESTAMP:
case Types.NEWDATE:
if (helpers.typeMatch(field.columnType, dateStrings, Types)) {
return `packet.readDateTimeString(${field.decimals});`;
}
return `packet.readDateTime('${timezone}');`;
case Types.TIME:
return 'packet.readTimeString()';
case Types.DECIMAL:
case Types.NEWDECIMAL:
if (config.decimalNumbers) {
return 'packet.parseLengthCodedFloat();';
}
return 'packet.readLengthCodedString("ascii");';
case Types.GEOMETRY:
return 'packet.parseGeometryValue();';
case Types.JSON:
// Since for JSON columns mysql always returns charset 63 (BINARY),
// we have to handle it according to JSON specs and use "utf8",
// see https://github.com/sidorares/node-mysql2/issues/409
return 'JSON.parse(packet.readLengthCodedString("utf8"));';
case Types.LONGLONG:
if (!supportBigNumbers) {
return unsigned
? 'packet.readInt64JSNumber();'
: 'packet.readSInt64JSNumber();';
}
if (bigNumberStrings) {
return unsigned
? 'packet.readInt64String();'
: 'packet.readSInt64String();';
}
return unsigned ? 'packet.readInt64();' : 'packet.readSInt64();';
default:
if (field.characterSet === Charsets.BINARY) {
return 'packet.readLengthCodedBuffer();';
}
return `packet.readLengthCodedString(CharsetToEncoding[fields[${fieldNum}].characterSet])`;
}
}
function compile(fields, options, config) {
const parserFn = genFunc();
let i = 0;
const nullBitmapLength = Math.floor((fields.length + 7 + 2) / 8);
/* eslint-disable no-trailing-spaces */
/* eslint-disable no-spaced-func */
/* eslint-disable no-unexpected-multiline */
parserFn('(function(){')(
'return function BinaryRow(packet, fields, options, CharsetToEncoding) {'
);
if (options.rowsAsArray) {
parserFn(`const result = new Array(${fields.length});`);
}
const resultTables = {};
let resultTablesArray = [];
if (options.nestTables === true) {
for (i = 0; i < fields.length; i++) {
resultTables[fields[i].table] = 1;
}
resultTablesArray = Object.keys(resultTables);
for (i = 0; i < resultTablesArray.length; i++) {
parserFn(`this[${helpers.srcEscape(resultTablesArray[i])}] = {};`);
}
}
parserFn('packet.readInt8();'); // status byte
for (i = 0; i < nullBitmapLength; ++i) {
parserFn(`const nullBitmaskByte${i} = packet.readInt8();`);
}
let lvalue = '';
let currentFieldNullBit = 4;
let nullByteIndex = 0;
let fieldName = '';
let tableName = '';
for (i = 0; i < fields.length; i++) {
fieldName = helpers.srcEscape(fields[i].name);
parserFn(`// ${fieldName}: ${typeNames[fields[i].columnType]}`);
if (typeof options.nestTables === 'string') {
tableName = helpers.srcEscape(fields[i].table);
lvalue = `this[${helpers.srcEscape(
fields[i].table + options.nestTables + fields[i].name
)}]`;
} else if (options.nestTables === true) {
tableName = helpers.srcEscape(fields[i].table);
lvalue = `this[${tableName}][${fieldName}]`;
} else if (options.rowsAsArray) {
lvalue = `result[${i.toString(10)}]`;
} else {
lvalue = `this[${helpers.srcEscape(fields[i].name)}]`;
}
// TODO: this used to be an optimisation ( if column marked as NOT_NULL don't include code to check null
// bitmap at all, but it seems that we can't rely on this flag, see #178
// TODO: benchmark performance difference
//
// if (fields[i].flags & FieldFlags.NOT_NULL) { // don't need to check null bitmap if field can't be null.
// result.push(lvalue + ' = ' + readCodeFor(fields[i], config));
// } else if (fields[i].columnType == Types.NULL) {
// result.push(lvalue + ' = null;');
// } else {
parserFn(`if (nullBitmaskByte${nullByteIndex} & ${currentFieldNullBit})`);
parserFn(`${lvalue} = null;`);
parserFn('else');
parserFn(`${lvalue} = ${readCodeFor(fields[i], config, options, i)}`);
// }
currentFieldNullBit *= 2;
if (currentFieldNullBit === 0x100) {
currentFieldNullBit = 1;
nullByteIndex++;
}
}
if (options.rowsAsArray) {
parserFn('return result;');
}
parserFn('};')('})()');
/* eslint-enable no-trailing-spaces */
/* eslint-enable no-spaced-func */
/* eslint-enable no-unexpected-multiline */
if (config.debug) {
helpers.printDebugWithCode(
'Compiled binary protocol row parser',
parserFn.toString()
);
}
return parserFn.toFunction();
}
function getBinaryParser(fields, options, config) {
return parserCache.getParser('binary', fields, options, config, compile);
}
module.exports = getBinaryParser;

59
node_modules/mysql2/lib/parsers/parser_cache.js generated vendored Normal file
View File

@ -0,0 +1,59 @@
'use strict';
const LRU = require('lru-cache');
const parserCache = new LRU({
max: 15000
});
function keyFromFields(type, fields, options, config) {
let res =
`${type}` +
`/${typeof options.nestTables}` +
`/${options.nestTables}` +
`/${options.rowsAsArray}` +
`/${options.supportBigNumbers || config.supportBigNumbers}` +
`/${options.bigNumberStrings || config.bigNumberStrings}` +
`/${typeof options.typeCast}` +
`/${options.timezone || config.timezone}` +
`/${options.decimalNumbers}` +
`/${options.dateStrings}`;
for (let i = 0; i < fields.length; ++i) {
const field = fields[i];
res += `/${field.name}:${field.columnType}:${field.flags}:${
field.characterSet
}`;
if (options.nestTables) {
res += `:${field.table}`
}
}
return res;
}
function getParser(type, fields, options, config, compiler) {
const key = keyFromFields(type, fields, options, config);
let parser = parserCache.get(key);
if (parser) {
return parser;
}
parser = compiler(fields, options, config);
parserCache.set(key, parser);
return parser;
}
function setMaxCache(max) {
parserCache.max = max;
}
function clearCache() {
parserCache.reset();
}
module.exports = {
getParser: getParser,
setMaxCache: setMaxCache,
clearCache: clearCache
};

29
node_modules/mysql2/lib/parsers/string.js generated vendored Normal file
View File

@ -0,0 +1,29 @@
'use strict';
const Iconv = require('iconv-lite');
exports.decode = function(buffer, encoding, options) {
if (Buffer.isEncoding(encoding)) {
return buffer.toString(encoding);
}
const decoder = Iconv.getDecoder(encoding, options || {});
const res = decoder.write(buffer);
const trail = decoder.end();
return trail ? res + trail : res;
};
exports.encode = function(string, encoding, options) {
if (Buffer.isEncoding(encoding)) {
return Buffer.from(string, encoding);
}
const encoder = Iconv.getEncoder(encoding, options || {});
const res = encoder.write(string);
const trail = encoder.end();
return trail && trail.length > 0 ? Buffer.concat([res, trail]) : res;
};

193
node_modules/mysql2/lib/parsers/text_parser.js generated vendored Normal file
View File

@ -0,0 +1,193 @@
'use strict';
const Types = require('../constants/types.js');
const Charsets = require('../constants/charsets.js');
const helpers = require('../helpers');
const genFunc = require('generate-function');
const parserCache = require('./parser_cache.js');
const typeNames = [];
for (const t in Types) {
typeNames[Types[t]] = t;
}
function readCodeFor(type, charset, encodingExpr, config, options) {
const supportBigNumbers =
options.supportBigNumbers || config.supportBigNumbers;
const bigNumberStrings = options.bigNumberStrings || config.bigNumberStrings;
const timezone = options.timezone || config.timezone;
const dateStrings = options.dateStrings || config.dateStrings;
switch (type) {
case Types.TINY:
case Types.SHORT:
case Types.LONG:
case Types.INT24:
case Types.YEAR:
return 'packet.parseLengthCodedIntNoBigCheck()';
case Types.LONGLONG:
if (supportBigNumbers && bigNumberStrings) {
return 'packet.parseLengthCodedIntString()';
}
return `packet.parseLengthCodedInt(${supportBigNumbers})`;
case Types.FLOAT:
case Types.DOUBLE:
return 'packet.parseLengthCodedFloat()';
case Types.NULL:
return 'packet.readLengthCodedNumber()';
case Types.DECIMAL:
case Types.NEWDECIMAL:
if (config.decimalNumbers) {
return 'packet.parseLengthCodedFloat()';
}
return 'packet.readLengthCodedString("ascii")';
case Types.DATE:
if (helpers.typeMatch(type, dateStrings, Types)) {
return 'packet.readLengthCodedString("ascii")';
}
return `packet.parseDate('${timezone}')`;
case Types.DATETIME:
case Types.TIMESTAMP:
if (helpers.typeMatch(type, dateStrings, Types)) {
return 'packet.readLengthCodedString("ascii")';
}
return `packet.parseDateTime('${timezone}')`;
case Types.TIME:
return 'packet.readLengthCodedString("ascii")';
case Types.GEOMETRY:
return 'packet.parseGeometryValue()';
case Types.JSON:
// Since for JSON columns mysql always returns charset 63 (BINARY),
// we have to handle it according to JSON specs and use "utf8",
// see https://github.com/sidorares/node-mysql2/issues/409
return 'JSON.parse(packet.readLengthCodedString("utf8"))';
default:
if (charset === Charsets.BINARY) {
return 'packet.readLengthCodedBuffer()';
}
return `packet.readLengthCodedString(${encodingExpr})`;
}
}
function compile(fields, options, config) {
// node-mysql typeCast compatibility wrapper
// see https://github.com/mysqljs/mysql/blob/96fdd0566b654436624e2375c7b6604b1f50f825/lib/protocol/packets/Field.js
function wrap(field, type, packet, encoding) {
return {
type: type,
length: field.columnLength,
db: field.schema,
table: field.table,
name: field.name,
string: function() {
return packet.readLengthCodedString(encoding);
},
buffer: function() {
return packet.readLengthCodedBuffer();
},
geometry: function() {
return packet.parseGeometryValue();
}
};
}
// use global typeCast if current query doesn't specify one
if (
typeof config.typeCast === 'function' &&
typeof options.typeCast !== 'function'
) {
options.typeCast = config.typeCast;
}
const parserFn = genFunc();
let i = 0;
/* eslint-disable no-trailing-spaces */
/* eslint-disable no-spaced-func */
/* eslint-disable no-unexpected-multiline */
parserFn('(function () {')(
'return function TextRow(packet, fields, options, CharsetToEncoding) {'
);
if (options.rowsAsArray) {
parserFn(`const result = new Array(${fields.length})`);
}
if (typeof options.typeCast === 'function') {
parserFn(`const wrap = ${wrap.toString()}`);
}
const resultTables = {};
let resultTablesArray = [];
if (options.nestTables === true) {
for (i = 0; i < fields.length; i++) {
resultTables[fields[i].table] = 1;
}
resultTablesArray = Object.keys(resultTables);
for (i = 0; i < resultTablesArray.length; i++) {
parserFn(`this[${helpers.srcEscape(resultTablesArray[i])}] = {};`);
}
}
let lvalue = '';
let fieldName = '';
for (i = 0; i < fields.length; i++) {
fieldName = helpers.srcEscape(fields[i].name);
parserFn(`// ${fieldName}: ${typeNames[fields[i].columnType]}`);
if (typeof options.nestTables === 'string') {
lvalue = `this[${helpers.srcEscape(
fields[i].table + options.nestTables + fields[i].name
)}]`;
} else if (options.nestTables === true) {
lvalue = `this[${helpers.srcEscape(fields[i].table)}][${fieldName}]`;
} else if (options.rowsAsArray) {
lvalue = `result[${i.toString(10)}]`;
} else {
lvalue = `this[${fieldName}]`;
}
const encodingExpr = `CharsetToEncoding[fields[${i}].characterSet]`;
const readCode = readCodeFor(
fields[i].columnType,
fields[i].characterSet,
encodingExpr,
config,
options
);
if (typeof options.typeCast === 'function') {
parserFn(
`${lvalue} = options.typeCast(wrap(fields[${i}], ${helpers.srcEscape(
typeNames[fields[i].columnType]
)}, packet, ${encodingExpr}), function() { return ${readCode};})`
);
} else if (options.typeCast === false) {
parserFn(`${lvalue} = packet.readLengthCodedBuffer();`);
} else {
parserFn(`${lvalue} = ${readCode};`);
}
}
if (options.rowsAsArray) {
parserFn('return result;');
}
parserFn('};')('})()');
/* eslint-enable no-trailing-spaces */
/* eslint-enable no-spaced-func */
/* eslint-enable no-unexpected-multiline */
if (config.debug) {
helpers.printDebugWithCode(
'Compiled text protocol row parser',
parserFn.toString()
);
}
return parserFn.toFunction();
}
function getTextParser(fields, options, config) {
return parserCache.getParser('text', fields, options, config, compile);
}
module.exports = getTextParser;

212
node_modules/mysql2/lib/pool.js generated vendored Normal file
View File

@ -0,0 +1,212 @@
'use strict';
const process = require('process');
const mysql = require('../index.js');
const EventEmitter = require('events').EventEmitter;
const PoolConnection = require('./pool_connection.js');
const Queue = require('denque');
const Connection = require('./connection.js');
function spliceConnection(queue, connection) {
const len = queue.length;
for (let i = 0; i < len; i++) {
if (queue.get(i) === connection) {
queue.removeOne(i);
break;
}
}
}
class Pool extends EventEmitter {
constructor(options) {
super();
this.config = options.config;
this.config.connectionConfig.pool = this;
this._allConnections = new Queue();
this._freeConnections = new Queue();
this._connectionQueue = new Queue();
this._closed = false;
}
promise(promiseImpl) {
const PromisePool = require('../promise').PromisePool;
return new PromisePool(this, promiseImpl);
}
getConnection(cb) {
if (this._closed) {
return process.nextTick(() => cb(new Error('Pool is closed.')));
}
let connection;
if (this._freeConnections.length > 0) {
connection = this._freeConnections.shift();
this.emit('acquire', connection);
return process.nextTick(() => cb(null, connection));
}
if (
this.config.connectionLimit === 0 ||
this._allConnections.length < this.config.connectionLimit
) {
connection = new PoolConnection(this, {
config: this.config.connectionConfig
});
this._allConnections.push(connection);
return connection.connect(err => {
if (this._closed) {
return cb(new Error('Pool is closed.'));
}
if (err) {
return cb(err);
}
this.emit('connection', connection);
this.emit('acquire', connection);
return cb(null, connection);
});
}
if (!this.config.waitForConnections) {
return process.nextTick(() => cb(new Error('No connections available.')));
}
if (
this.config.queueLimit &&
this._connectionQueue.length >= this.config.queueLimit
) {
return cb(new Error('Queue limit reached.'));
}
this.emit('enqueue');
return this._connectionQueue.push(cb);
}
releaseConnection(connection) {
let cb;
if (!connection._pool) {
// The connection has been removed from the pool and is no longer good.
if (this._connectionQueue.length) {
cb = this._connectionQueue.shift();
process.nextTick(this.getConnection.bind(this, cb));
}
} else if (this._connectionQueue.length) {
cb = this._connectionQueue.shift();
process.nextTick(cb.bind(null, null, connection));
} else {
this._freeConnections.push(connection);
this.emit('release', connection);
}
}
end(cb) {
this._closed = true;
if (typeof cb !== 'function') {
cb = function(err) {
if (err) {
throw err;
}
};
}
let calledBack = false;
let closedConnections = 0;
let connection;
const endCB = function(err) {
if (calledBack) {
return;
}
if (err || ++closedConnections >= this._allConnections.length) {
calledBack = true;
cb(err);
return;
}
}.bind(this);
if (this._allConnections.length === 0) {
endCB();
return;
}
for (let i = 0; i < this._allConnections.length; i++) {
connection = this._allConnections.get(i);
connection._realEnd(endCB);
}
}
query(sql, values, cb) {
const cmdQuery = Connection.createQuery(
sql,
values,
cb,
this.config.connectionConfig
);
if (typeof cmdQuery.namedPlaceholders === 'undefined') {
cmdQuery.namedPlaceholders = this.config.connectionConfig.namedPlaceholders;
}
this.getConnection((err, conn) => {
if (err) {
if (typeof cmdQuery.onResult === 'function') {
cmdQuery.onResult(err);
} else {
cmdQuery.emit('error', err);
}
return;
}
try {
conn.query(cmdQuery).once('end', () => {
conn.release();
});
} catch (e) {
conn.release();
throw e;
}
});
return cmdQuery;
}
execute(sql, values, cb) {
// TODO construct execute command first here and pass it to connection.execute
// so that polymorphic arguments logic is there in one place
if (typeof values === 'function') {
cb = values;
values = [];
}
this.getConnection((err, conn) => {
if (err) {
return cb(err);
}
try {
conn.execute(sql, values, cb).once('end', () => {
conn.release();
});
} catch (e) {
conn.release();
throw e;
}
});
}
_removeConnection(connection) {
// Remove connection from all connections
spliceConnection(this._allConnections, connection);
// Remove connection from free connections
spliceConnection(this._freeConnections, connection);
this.releaseConnection(connection);
}
format(sql, values) {
return mysql.format(
sql,
values,
this.config.connectionConfig.stringifyObjects,
this.config.connectionConfig.timezone
);
}
escape(value) {
return mysql.escape(
value,
this.config.connectionConfig.stringifyObjects,
this.config.connectionConfig.timezone
);
}
escapeId(value) {
return mysql.escapeId(value, false);
}
}
module.exports = Pool;

226
node_modules/mysql2/lib/pool_cluster.js generated vendored Normal file
View File

@ -0,0 +1,226 @@
'use strict';
const process = require('process');
const Pool = require('./pool.js');
const PoolConfig = require('./pool_config.js');
const EventEmitter = require('events').EventEmitter;
/**
* Selector
*/
const makeSelector = {
RR() {
let index = 0;
return clusterIds => clusterIds[index++ % clusterIds.length];
},
RANDOM() {
return clusterIds =>
clusterIds[Math.floor(Math.random() * clusterIds.length)];
},
ORDER() {
return clusterIds => clusterIds[0];
}
};
class PoolNamespace {
constructor(cluster, pattern, selector) {
this._cluster = cluster;
this._pattern = pattern;
this._selector = makeSelector[selector]();
}
getConnection(cb) {
const clusterNode = this._getClusterNode();
if (clusterNode === null) {
return cb(new Error('Pool does Not exists.'));
}
return this._cluster._getConnection(clusterNode, (err, connection) => {
if (err) {
return cb(err);
}
if (connection === 'retry') {
return this.getConnection(cb);
}
return cb(null, connection);
});
}
_getClusterNode() {
const foundNodeIds = this._cluster._findNodeIds(this._pattern);
if (foundNodeIds.length === 0) {
return null;
}
const nodeId =
foundNodeIds.length === 1
? foundNodeIds[0]
: this._selector(foundNodeIds);
return this._cluster._getNode(nodeId);
}
}
class PoolCluster extends EventEmitter {
constructor(config) {
super();
config = config || {};
this._canRetry =
typeof config.canRetry === 'undefined' ? true : config.canRetry;
this._removeNodeErrorCount = config.removeNodeErrorCount || 5;
this._defaultSelector = config.defaultSelector || 'RR';
this._closed = false;
this._lastId = 0;
this._nodes = {};
this._serviceableNodeIds = [];
this._namespaces = {};
this._findCaches = {};
}
of(pattern, selector) {
pattern = pattern || '*';
selector = selector || this._defaultSelector;
selector = selector.toUpperCase();
if (!makeSelector[selector] === 'undefined') {
selector = this._defaultSelector;
}
const key = pattern + selector;
if (typeof this._namespaces[key] === 'undefined') {
this._namespaces[key] = new PoolNamespace(this, pattern, selector);
}
return this._namespaces[key];
}
add(id, config) {
if (typeof id === 'object') {
config = id;
id = `CLUSTER::${++this._lastId}`;
}
if (typeof this._nodes[id] === 'undefined') {
this._nodes[id] = {
id: id,
errorCount: 0,
pool: new Pool({ config: new PoolConfig(config) })
};
this._serviceableNodeIds.push(id);
this._clearFindCaches();
}
}
getConnection(pattern, selector, cb) {
let namespace;
if (typeof pattern === 'function') {
cb = pattern;
namespace = this.of();
} else {
if (typeof selector === 'function') {
cb = selector;
selector = this._defaultSelector;
}
namespace = this.of(pattern, selector);
}
namespace.getConnection(cb);
}
end(callback) {
const cb =
callback !== undefined
? callback
: err => {
if (err) {
throw err;
}
};
if (this._closed) {
process.nextTick(cb);
return;
}
this._closed = true;
let calledBack = false;
let waitingClose = 0;
const onEnd = err => {
if (!calledBack && (err || --waitingClose <= 0)) {
calledBack = true;
return cb(err);
}
};
for (const id in this._nodes) {
waitingClose++;
this._nodes[id].pool.end(onEnd);
}
if (waitingClose === 0) {
process.nextTick(onEnd);
}
}
_findNodeIds(pattern) {
if (typeof this._findCaches[pattern] !== 'undefined') {
return this._findCaches[pattern];
}
let foundNodeIds;
if (pattern === '*') {
// all
foundNodeIds = this._serviceableNodeIds;
} else if (this._serviceableNodeIds.indexOf(pattern) !== -1) {
// one
foundNodeIds = [pattern];
} else {
// wild matching
const keyword = pattern.substring(pattern.length - 1, 0);
foundNodeIds = this._serviceableNodeIds.filter(id =>
id.startsWith(keyword)
);
}
this._findCaches[pattern] = foundNodeIds;
return foundNodeIds;
}
_getNode(id) {
return this._nodes[id] || null;
}
_increaseErrorCount(node) {
if (++node.errorCount >= this._removeNodeErrorCount) {
const index = this._serviceableNodeIds.indexOf(node.id);
if (index !== -1) {
this._serviceableNodeIds.splice(index, 1);
delete this._nodes[node.id];
this._clearFindCaches();
node.pool.end();
this.emit('remove', node.id);
}
}
}
_decreaseErrorCount(node) {
if (node.errorCount > 0) {
--node.errorCount;
}
}
_getConnection(node, cb) {
node.pool.getConnection((err, connection) => {
if (err) {
this._increaseErrorCount(node);
if (this._canRetry) {
// REVIEW: this seems wrong?
this.emit('warn', err);
// eslint-disable-next-line no-console
console.warn(`[Error] PoolCluster : ${err}`);
return cb(null, 'retry');
}
return cb(err);
}
this._decreaseErrorCount(node);
connection._clusterId = node.id;
return cb(null, connection);
});
}
_clearFindCaches() {
this._findCaches = {};
}
}
module.exports = PoolCluster;

24
node_modules/mysql2/lib/pool_config.js generated vendored Normal file
View File

@ -0,0 +1,24 @@
'use strict';
const ConnectionConfig = require('./connection_config.js');
class PoolConfig {
constructor(options) {
if (typeof options === 'string') {
options = ConnectionConfig.parseUrl(options);
}
this.connectionConfig = new ConnectionConfig(options);
this.waitForConnections =
options.waitForConnections === undefined
? true
: Boolean(options.waitForConnections);
this.connectionLimit = isNaN(options.connectionLimit)
? 10
: Number(options.connectionLimit);
this.queueLimit = isNaN(options.queueLimit)
? 0
: Number(options.queueLimit);
}
}
module.exports = PoolConfig;

65
node_modules/mysql2/lib/pool_connection.js generated vendored Normal file
View File

@ -0,0 +1,65 @@
'use strict';
const Connection = require('../index.js').Connection;
class PoolConnection extends Connection {
constructor(pool, options) {
super(options);
this._pool = pool;
// When a fatal error occurs the connection's protocol ends, which will cause
// the connection to end as well, thus we only need to watch for the end event
// and we will be notified of disconnects.
// REVIEW: Moved to `once`
this.once('end', () => {
this._removeFromPool();
});
this.once('error', () => {
this._removeFromPool();
});
}
release() {
if (!this._pool || this._pool._closed) {
return;
}
this._pool.releaseConnection(this);
}
promise(promiseImpl) {
const PromisePoolConnection = require('../promise').PromisePoolConnection;
return new PromisePoolConnection(this, promiseImpl);
}
end() {
const err = new Error(
'Calling conn.end() to release a pooled connection is ' +
'deprecated. In next version calling conn.end() will be ' +
'restored to default conn.end() behavior. Use ' +
'conn.release() instead.'
);
this.emit('warn', err);
// eslint-disable-next-line no-console
console.warn(err.message);
this.release();
}
destroy() {
this._removeFromPool();
super.destroy();
}
_removeFromPool() {
if (!this._pool || this._pool._closed) {
return;
}
const pool = this._pool;
this._pool = null;
pool._removeConnection(this);
}
}
PoolConnection.statementKey = Connection.statementKey;
module.exports = PoolConnection;
// TODO: Remove this when we are removing PoolConnection#end
PoolConnection.prototype._realEnd = Connection.prototype.end;

38
node_modules/mysql2/lib/results_stream.js generated vendored Normal file
View File

@ -0,0 +1,38 @@
'use strict';
const Readable = require('stream').Readable;
// copy-paste from https://github.com/mysqljs/mysql/blob/master/lib/protocol/sequences/Query.js
module.exports = function(command, connectionStream) {
command.stream = function(options) {
let stream;
options = options || {};
options.objectMode = true;
(stream = new Readable(options)),
(stream._read = function() {
connectionStream.resume();
});
this.on('result', (row, i) => {
if (!stream.push(row)) {
connectionStream.pause();
}
stream.emit('result', row, i); // replicate old emitter
});
this.on('error', err => {
stream.emit('error', err); // Pass on any errors
});
this.on('end', () => {
stream.push(null); // pushing null, indicating EOF
});
this.on('fields', (fields, i) => {
stream.emit('fields', fields, i); // replicate old emitter
});
return stream;
};
};

37
node_modules/mysql2/lib/server.js generated vendored Normal file
View File

@ -0,0 +1,37 @@
'use strict';
const net = require('net');
const EventEmitter = require('events').EventEmitter;
const Connection = require('./connection');
const ConnectionConfig = require('./connection_config');
// TODO: inherit Server from net.Server
class Server extends EventEmitter {
constructor() {
super();
this.connections = [];
this._server = net.createServer(this._handleConnection.bind(this));
}
_handleConnection(socket) {
const connectionConfig = new ConnectionConfig({
stream: socket,
isServer: true
});
const connection = new Connection({ config: connectionConfig });
this.emit('connection', connection);
}
listen(port) {
this._port = port;
this._server.listen.apply(this._server, arguments);
return this;
}
close(cb) {
this._server.close(cb);
}
}
module.exports = Server;