aboutsummaryrefslogtreecommitdiff
path: root/node_modules/mysql2/lib/commands
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.h.kronqvist@gmail.com>2022-03-05 19:02:27 +0200
committerJoel Kronqvist <joel.h.kronqvist@gmail.com>2022-03-05 19:02:27 +0200
commit5d309ff52cd399a6b71968a6b9a70c8ac0b98981 (patch)
tree360f7eb50f956e2367ef38fa1fc6ac7ac5258042 /node_modules/mysql2/lib/commands
parentb500a50f1b97d93c98b36ed9a980f8188d648147 (diff)
downloadLYLLRuoka-5d309ff52cd399a6b71968a6b9a70c8ac0b98981.tar.gz
LYLLRuoka-5d309ff52cd399a6b71968a6b9a70c8ac0b98981.zip
Added node_modules for the updating to work properly.
Diffstat (limited to 'node_modules/mysql2/lib/commands')
-rw-r--r--node_modules/mysql2/lib/commands/auth_switch.js106
-rw-r--r--node_modules/mysql2/lib/commands/binlog_dump.js109
-rw-r--r--node_modules/mysql2/lib/commands/change_user.js47
-rw-r--r--node_modules/mysql2/lib/commands/client_handshake.js200
-rw-r--r--node_modules/mysql2/lib/commands/close_statement.js18
-rw-r--r--node_modules/mysql2/lib/commands/command.js55
-rw-r--r--node_modules/mysql2/lib/commands/execute.js107
-rw-r--r--node_modules/mysql2/lib/commands/index.js27
-rw-r--r--node_modules/mysql2/lib/commands/ping.js36
-rw-r--r--node_modules/mysql2/lib/commands/prepare.js130
-rw-r--r--node_modules/mysql2/lib/commands/query.js321
-rw-r--r--node_modules/mysql2/lib/commands/quit.js29
-rw-r--r--node_modules/mysql2/lib/commands/register_slave.js27
-rw-r--r--node_modules/mysql2/lib/commands/server_handshake.js162
14 files changed, 1374 insertions, 0 deletions
diff --git a/node_modules/mysql2/lib/commands/auth_switch.js b/node_modules/mysql2/lib/commands/auth_switch.js
new file mode 100644
index 0000000..9e0b527
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/auth_switch.js
@@ -0,0 +1,106 @@
+// This file was modified by Oracle on July 5, 2021.
+// Errors generated by asynchronous authentication plugins are now being
+// handled and subsequently emitted at the command level.
+// Modifications copyright (c) 2021, Oracle and/or its affiliates.
+
+'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 authSwitchPluginError(error, command) {
+ // Authentication errors are fatal
+ error.code = 'AUTH_SWITCH_PLUGIN_ERROR';
+ error.fatal = true;
+
+ command.emit('error', error);
+}
+
+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) {
+ return authSwitchPluginError(err, command);
+ }
+ 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());
+ }
+ }).catch(err => {
+ authSwitchPluginError(err, command);
+ });
+}
+
+function authSwitchRequestMoreData(packet, connection, command) {
+ const { data } = Packets.AuthSwitchRequestMoreData.fromPacket(packet);
+
+ if (connection.config.authSwitchHandler) {
+ const legacySwitchHandler = connection.config.authSwitchHandler;
+ warnLegacyAuthSwitch();
+ legacySwitchHandler({ pluginData: data }, (err, data) => {
+ if (err) {
+ return authSwitchPluginError(err, command);
+ }
+ 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());
+ }
+ }).catch(err => {
+ authSwitchPluginError(err, command);
+ });
+}
+
+module.exports = {
+ authSwitchRequest,
+ authSwitchRequestMoreData
+};
diff --git a/node_modules/mysql2/lib/commands/binlog_dump.js b/node_modules/mysql2/lib/commands/binlog_dump.js
new file mode 100644
index 0000000..be00031
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/binlog_dump.js
@@ -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;
diff --git a/node_modules/mysql2/lib/commands/change_user.js b/node_modules/mysql2/lib/commands/change_user.js
new file mode 100644
index 0000000..e2b2a09
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/change_user.js
@@ -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;
diff --git a/node_modules/mysql2/lib/commands/client_handshake.js b/node_modules/mysql2/lib/commands/client_handshake.js
new file mode 100644
index 0000000..c5e5de0
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/client_handshake.js
@@ -0,0 +1,200 @@
+// This file was modified by Oracle on June 17, 2021.
+// Handshake errors are now maked as fatal and the corresponding events are
+// emitted in the command instance itself.
+// Modifications copyright (c) 2021, Oracle and/or its affiliates.
+
+'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) {
+ // Authentication errors are fatal
+ err.code = 'AUTH_SWITCH_PLUGIN_ERROR';
+ err.fatal = true;
+
+ if (this.onResult) {
+ this.onResult(err);
+ } else {
+ this.emit('error', err);
+ }
+ return null;
+ }
+ }
+ if (marker !== 0) {
+ const err = new Error('Unexpected packet during handshake phase');
+ // Unknown handshake errors are fatal
+ err.code = 'HANDSHAKE_UNKNOWN_ERROR';
+ err.fatal = true;
+
+ if (this.onResult) {
+ this.onResult(err);
+ } else {
+ this.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;
diff --git a/node_modules/mysql2/lib/commands/close_statement.js b/node_modules/mysql2/lib/commands/close_statement.js
new file mode 100644
index 0000000..15919c1
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/close_statement.js
@@ -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;
diff --git a/node_modules/mysql2/lib/commands/command.js b/node_modules/mysql2/lib/commands/command.js
new file mode 100644
index 0000000..659086f
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/command.js
@@ -0,0 +1,55 @@
+'use strict';
+
+const EventEmitter = require('events').EventEmitter;
+const Timers = require('timers');
+
+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);
+ err.sql = this.sql || this.query;
+ if (this.queryTimeout) {
+ Timers.clearTimeout(this.queryTimeout);
+ this.queryTimeout = null;
+ }
+ 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;
diff --git a/node_modules/mysql2/lib/commands/execute.js b/node_modules/mysql2/lib/commands/execute.js
new file mode 100644
index 0000000..8ab7304
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/execute.js
@@ -0,0 +1,107 @@
+'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.timeout = options.timeout;
+ this.queryTimeout = null;
+ 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);
+ this._setTimeout();
+ 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 = new (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._setTimeout = Query.prototype._setTimeout;
+Execute.prototype._handleTimeoutError = Query.prototype._handleTimeoutError;
+Execute.prototype.row = Query.prototype.row;
+Execute.prototype.stream = Query.prototype.stream;
+
+module.exports = Execute;
diff --git a/node_modules/mysql2/lib/commands/index.js b/node_modules/mysql2/lib/commands/index.js
new file mode 100644
index 0000000..74a32ae
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/index.js
@@ -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
+};
diff --git a/node_modules/mysql2/lib/commands/ping.js b/node_modules/mysql2/lib/commands/ping.js
new file mode 100644
index 0000000..dc820ef
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/ping.js
@@ -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;
diff --git a/node_modules/mysql2/lib/commands/prepare.js b/node_modules/mysql2/lib/commands/prepare.js
new file mode 100644
index 0000000..49608b3
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/prepare.js
@@ -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;
diff --git a/node_modules/mysql2/lib/commands/query.js b/node_modules/mysql2/lib/commands/query.js
new file mode 100644
index 0000000..e51da3c
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/query.js
@@ -0,0 +1,321 @@
+'use strict';
+
+const process = require('process');
+const Timers = require('timers');
+
+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 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.timeout = options.timeout;
+ this.queryTimeout = null;
+ 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);
+ }
+
+ /* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
+ 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);
+ this._setTimeout();
+
+ const cmdPacket = new Packets.Query(
+ this.sql,
+ connection.config.charsetNumber
+ );
+ connection.writePacket(cmdPacket.toPacket(1));
+ return Query.prototype.resultsetHeader;
+ }
+
+ done() {
+ this._unpipeStream();
+ // if all ready timeout, return null directly
+ if (this.timeout && !this.queryTimeout) {
+ return null;
+ }
+ // else clear timer
+ if (this.queryTimeout) {
+ Timers.clearTimeout(this.queryTimeout);
+ this.queryTimeout = null;
+ }
+ 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 = new (getTextParser(fields, this.options, connection.config))(fields);
+ 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;
+ }
+
+ /* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
+ row(packet, _connection) {
+ 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 = this._rowParser.next(
+ packet,
+ this._fields[this._resultIndex],
+ this.options
+ );
+ } 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;
+ }
+
+ _setTimeout() {
+ if (this.timeout) {
+ const timeoutHandler = this._handleTimeoutError.bind(this);
+ this.queryTimeout = Timers.setTimeout(
+ timeoutHandler,
+ this.timeout
+ );
+ }
+ }
+
+ _handleTimeoutError() {
+ if (this.queryTimeout) {
+ Timers.clearTimeout(this.queryTimeout);
+ this.queryTimeout = null;
+ }
+
+ const err = new Error('Query inactivity timeout');
+ err.errorno = 'PROTOCOL_SEQUENCE_TIMEOUT';
+ err.code = 'PROTOCOL_SEQUENCE_TIMEOUT';
+ err.syscall = 'query';
+
+ if (this.onResult) {
+ this.onResult(err);
+ } else {
+ this.emit('error', err);
+ }
+ }
+}
+
+Query.prototype.catch = Query.prototype.then;
+
+module.exports = Query;
diff --git a/node_modules/mysql2/lib/commands/quit.js b/node_modules/mysql2/lib/commands/quit.js
new file mode 100644
index 0000000..b9fe355
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/quit.js
@@ -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;
diff --git a/node_modules/mysql2/lib/commands/register_slave.js b/node_modules/mysql2/lib/commands/register_slave.js
new file mode 100644
index 0000000..4ebfe61
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/register_slave.js
@@ -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;
diff --git a/node_modules/mysql2/lib/commands/server_handshake.js b/node_modules/mysql2/lib/commands/server_handshake.js
new file mode 100644
index 0000000..7dbba5f
--- /dev/null
+++ b/node_modules/mysql2/lib/commands/server_handshake.js
@@ -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)
+*/