aboutsummaryrefslogtreecommitdiff
path: root/node_modules/mysql2/lib/packets
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/packets
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/packets')
-rw-r--r--node_modules/mysql2/lib/packets/auth_switch_request.js38
-rw-r--r--node_modules/mysql2/lib/packets/auth_switch_request_more_data.js33
-rw-r--r--node_modules/mysql2/lib/packets/auth_switch_response.js30
-rw-r--r--node_modules/mysql2/lib/packets/binary_row.js48
-rw-r--r--node_modules/mysql2/lib/packets/binlog_dump.js33
-rw-r--r--node_modules/mysql2/lib/packets/binlog_query_statusvars.js115
-rw-r--r--node_modules/mysql2/lib/packets/change_user.js97
-rw-r--r--node_modules/mysql2/lib/packets/close_statement.js21
-rw-r--r--node_modules/mysql2/lib/packets/column_definition.js140
-rw-r--r--node_modules/mysql2/lib/packets/execute.js150
-rw-r--r--node_modules/mysql2/lib/packets/handshake.js112
-rw-r--r--node_modules/mysql2/lib/packets/handshake_response.js145
-rw-r--r--node_modules/mysql2/lib/packets/index.js146
-rw-r--r--node_modules/mysql2/lib/packets/packet.js919
-rw-r--r--node_modules/mysql2/lib/packets/prepare_statement.js27
-rw-r--r--node_modules/mysql2/lib/packets/prepared_statement_header.js16
-rw-r--r--node_modules/mysql2/lib/packets/query.js27
-rw-r--r--node_modules/mysql2/lib/packets/register_slave.js46
-rw-r--r--node_modules/mysql2/lib/packets/resultset_header.js110
-rw-r--r--node_modules/mysql2/lib/packets/ssl_request.js25
-rw-r--r--node_modules/mysql2/lib/packets/text_row.js47
21 files changed, 2325 insertions, 0 deletions
diff --git a/node_modules/mysql2/lib/packets/auth_switch_request.js b/node_modules/mysql2/lib/packets/auth_switch_request.js
new file mode 100644
index 0000000..a05abf2
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/auth_switch_request.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/auth_switch_request_more_data.js b/node_modules/mysql2/lib/packets/auth_switch_request_more_data.js
new file mode 100644
index 0000000..7294d08
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/auth_switch_request_more_data.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/auth_switch_response.js b/node_modules/mysql2/lib/packets/auth_switch_response.js
new file mode 100644
index 0000000..2a821a0
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/auth_switch_response.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/binary_row.js b/node_modules/mysql2/lib/packets/binary_row.js
new file mode 100644
index 0000000..e78b856
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/binary_row.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/binlog_dump.js b/node_modules/mysql2/lib/packets/binlog_dump.js
new file mode 100644
index 0000000..e014837
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/binlog_dump.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/binlog_query_statusvars.js b/node_modules/mysql2/lib/packets/binlog_query_statusvars.js
new file mode 100644
index 0000000..8e45fb5
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/binlog_query_statusvars.js
@@ -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;
+};
diff --git a/node_modules/mysql2/lib/packets/change_user.js b/node_modules/mysql2/lib/packets/change_user.js
new file mode 100644
index 0000000..3fa3937
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/change_user.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/close_statement.js b/node_modules/mysql2/lib/packets/close_statement.js
new file mode 100644
index 0000000..d8be98d
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/close_statement.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/column_definition.js b/node_modules/mysql2/lib/packets/column_definition.js
new file mode 100644
index 0000000..29df846
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/column_definition.js
@@ -0,0 +1,140 @@
+'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,
+ this.encoding === 'binary' ? this._clientEncoding : this.encoding,
+ _nameStart,
+ _nameStart + _nameLength
+ );
+ 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() {
+ return this.schema;
+ }
+}
+
+const addString = function(name) {
+ Object.defineProperty(ColumnDefinition.prototype, name, {
+ get: function() {
+ const start = this[`_${name}Start`];
+ const end = start + this[`_${name}Length`];
+ const val = StringParser.decode(
+ this._buf,
+ this.encoding === 'binary' ? this._clientEncoding : this.encoding,
+ start,
+ end
+ );
+
+ Object.defineProperty(this, name, {
+ value: val,
+ writable: false,
+ configurable: false,
+ enumerable: false
+ });
+
+ return val;
+ }
+ });
+};
+
+addString('catalog');
+addString('schema');
+addString('table');
+addString('orgTable');
+addString('orgName');
+
+module.exports = ColumnDefinition;
diff --git a/node_modules/mysql2/lib/packets/execute.js b/node_modules/mysql2/lib/packets/execute.js
new file mode 100644
index 0000000..c612f66
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/execute.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/handshake.js b/node_modules/mysql2/lib/packets/handshake.js
new file mode 100644
index 0000000..239387c
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/handshake.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/handshake_response.js b/node_modules/mysql2/lib/packets/handshake_response.js
new file mode 100644
index 0000000..b2dee38
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/handshake_response.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/index.js b/node_modules/mysql2/lib/packets/index.js
new file mode 100644
index 0000000..e5bb390
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/index.js
@@ -0,0 +1,146 @@
+// This file was modified by Oracle on June 1, 2021.
+// A utility method was introduced to generate an Error instance from a
+// binary server packet.
+// Modifications copyright (c) 2021, Oracle and/or its affiliates.
+
+'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;
+ }
+
+ static fromPacket(packet) {
+ packet.readInt8(); // marker
+ const code = packet.readInt16();
+ packet.readString(1, 'ascii'); // sql state marker
+ // The SQL state of the ERR_Packet which is always 5 bytes long.
+ // https://dev.mysql.com/doc/dev/mysql-server/8.0.11/page_protocol_basic_dt_strings.html#sect_protocol_basic_dt_string_fix
+ packet.readString(5, 'ascii'); // sql state (ignore for now)
+ const message = packet.readNullTerminatedString('utf8');
+ const error = new Error();
+ error.message = message;
+ error.code = code;
+ return error;
+ }
+}
+
+exports.Error = Error;
diff --git a/node_modules/mysql2/lib/packets/packet.js b/node_modules/mysql2/lib/packets/packet.js
new file mode 100644
index 0000000..ccf3a84
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/packet.js
@@ -0,0 +1,919 @@
+// This file was modified by Oracle on June 1, 2021.
+// A comment describing some changes in the strict default SQL mode regarding
+// non-standard dates was introduced.
+// Modifications copyright (c) 2021, Oracle and/or its affiliates.
+
+'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;
+ }
+ // NO_ZERO_DATE mode and NO_ZERO_IN_DATE mode are part of the strict
+ // default SQL mode used by MySQL 8.0. This means that non-standard
+ // dates like '0000-00-00' become NULL. For older versions and other
+ // possible MySQL flavours we still need to account for the
+ // non-standard behaviour.
+ 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;
+ }
+ // Format follows mySQL TIME format ([-][h]hh:mm:ss[.u[u[u[u[u[u]]]]]])
+ // For positive times below 24 hours, this makes it equal to ISO 8601 times
+ return (
+ (sign === -1 ? '-' : '') +
+ [leftPad(2, d * 24 + H), leftPad(2, M), leftPad(2, S)].join(':') +
+ (ms ? `.${ms}`.replace(/0+$/, '') : '')
+ );
+ }
+
+ 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,
+ encoding,
+ this.offset - len,
+ this.offset
+ );
+ }
+
+ 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, encoding, start, end);
+ }
+
+ // 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,
+ encoding,
+ this.offset - len,
+ this.offset
+ );
+ }
+
+ 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;
diff --git a/node_modules/mysql2/lib/packets/prepare_statement.js b/node_modules/mysql2/lib/packets/prepare_statement.js
new file mode 100644
index 0000000..d53c222
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/prepare_statement.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/prepared_statement_header.js b/node_modules/mysql2/lib/packets/prepared_statement_header.js
new file mode 100644
index 0000000..70b263a
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/prepared_statement_header.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/query.js b/node_modules/mysql2/lib/packets/query.js
new file mode 100644
index 0000000..b650b35
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/query.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/register_slave.js b/node_modules/mysql2/lib/packets/register_slave.js
new file mode 100644
index 0000000..26e802f
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/register_slave.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/resultset_header.js b/node_modules/mysql2/lib/packets/resultset_header.js
new file mode 100644
index 0000000..e6a8cd4
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/resultset_header.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/ssl_request.js b/node_modules/mysql2/lib/packets/ssl_request.js
new file mode 100644
index 0000000..69eec24
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/ssl_request.js
@@ -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;
diff --git a/node_modules/mysql2/lib/packets/text_row.js b/node_modules/mysql2/lib/packets/text_row.js
new file mode 100644
index 0000000..af9ab93
--- /dev/null
+++ b/node_modules/mysql2/lib/packets/text_row.js
@@ -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;