API inicial
This commit is contained in:
276
node_modules/mariadb/lib/cmd/batch-bulk.js
generated
vendored
Normal file
276
node_modules/mariadb/lib/cmd/batch-bulk.js
generated
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
'use strict';
|
||||
|
||||
const CommonBinary = require('./common-binary-cmd');
|
||||
const Errors = require('../misc/errors');
|
||||
const Parse = require('../misc/parse');
|
||||
const BulkPacket = require('../io/bulk-packet');
|
||||
|
||||
/**
|
||||
* Protocol COM_STMT_BULK_EXECUTE
|
||||
* see : https://mariadb.com/kb/en/library/com_stmt_bulk_execute/
|
||||
*/
|
||||
class BatchBulk extends CommonBinary {
|
||||
constructor(resolve, reject, options, connOpts, sql, values) {
|
||||
super(resolve, reject, options, connOpts, sql, values);
|
||||
this.onPacketReceive = this.readPrepareResultPacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send COM_STMT_BULK_EXECUTE
|
||||
*
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
*/
|
||||
start(out, opts, info) {
|
||||
this.sending = true;
|
||||
this.info = info;
|
||||
this.values = this.initialValues;
|
||||
|
||||
if (this.opts.timeout) {
|
||||
const err = Errors.createError(
|
||||
'Cannot use timeout for Batch statement',
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_TIMEOUT_NOT_SUPPORTED
|
||||
);
|
||||
this.emit('send_end');
|
||||
this.throwError(err, info);
|
||||
return;
|
||||
}
|
||||
|
||||
let questionMarkSql = this.sql;
|
||||
if (this.opts.namedPlaceholders) {
|
||||
const res = Parse.searchPlaceholder(
|
||||
this.sql,
|
||||
info,
|
||||
this.initialValues,
|
||||
this.displaySql.bind(this)
|
||||
);
|
||||
questionMarkSql = res.sql;
|
||||
this.values = res.values;
|
||||
}
|
||||
|
||||
if (!this.validateParameters(info)) {
|
||||
this.sending = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//send COM_STMT_PREPARE command
|
||||
this.out = out;
|
||||
this.packet = new BulkPacket(this.opts, out, this.values[0]);
|
||||
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x16);
|
||||
out.writeString(questionMarkSql);
|
||||
out.flushBuffer(true);
|
||||
|
||||
if (this.opts.pipelining) {
|
||||
out.startPacket(this);
|
||||
this.valueIdx = 0;
|
||||
this.sendQueries();
|
||||
} else {
|
||||
this.out = out;
|
||||
}
|
||||
}
|
||||
|
||||
sendQueries() {
|
||||
let flushed = false;
|
||||
while (!flushed && this.sending && this.valueIdx < this.values.length) {
|
||||
this.valueRow = this.values[this.valueIdx++];
|
||||
|
||||
//********************************************
|
||||
// send params
|
||||
//********************************************
|
||||
const len = this.valueRow.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
const value = this.valueRow[i];
|
||||
if (value === null) {
|
||||
flushed = this.packet.writeInt8(0x01) || flushed;
|
||||
continue;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
// param has no stream. directly write in buffer
|
||||
//********************************************
|
||||
flushed = this.writeParam(this.packet, value, this.opts, this.info) || flushed;
|
||||
}
|
||||
const last = this.valueIdx === this.values.length;
|
||||
flushed = this.packet.mark(last, last ? null : this.values[this.valueIdx]) || flushed;
|
||||
}
|
||||
|
||||
if (this.valueIdx < this.values.length && !this.packet.haveErrorResponse) {
|
||||
//there is still data to send
|
||||
setImmediate(this.sendQueries.bind(this));
|
||||
} else {
|
||||
if (this.sending && this.valueIdx === this.values.length) this.emit('send_end');
|
||||
this.sending = false;
|
||||
}
|
||||
}
|
||||
|
||||
displaySql() {
|
||||
if (this.opts && this.initialValues) {
|
||||
if (this.sql.length > this.opts.debugLen) {
|
||||
return 'sql: ' + this.sql.substring(0, this.opts.debugLen) + '...';
|
||||
}
|
||||
|
||||
let sqlMsg = 'sql: ' + this.sql + ' - parameters:';
|
||||
sqlMsg += '[';
|
||||
for (let i = 0; i < this.initialValues.length; i++) {
|
||||
if (i !== 0) sqlMsg += ',';
|
||||
let param = this.initialValues[i];
|
||||
sqlMsg = this.logParameters(sqlMsg, param);
|
||||
if (sqlMsg.length > this.opts.debugLen) {
|
||||
sqlMsg = sqlMsg.substr(0, this.opts.debugLen) + '...';
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlMsg += ']';
|
||||
return sqlMsg;
|
||||
}
|
||||
return 'sql: ' + this.sql + ' - parameters:[]';
|
||||
}
|
||||
|
||||
success(val) {
|
||||
this.packet.waitingResponseNo--;
|
||||
|
||||
if (!this.opts.pipelining && this.packet.statementId === -1) {
|
||||
this.packet.statementId = this.statementId;
|
||||
this.out.startPacket(this);
|
||||
this.valueIdx = 0;
|
||||
this.sendQueries();
|
||||
this._responseIndex++;
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.sending && this.packet.waitingResponseNo === 0) {
|
||||
//send COM_STMT_CLOSE packet
|
||||
if (!this.firstError || !this.firstError.fatal) {
|
||||
this.sequenceNo = -1;
|
||||
this.compressSequenceNo = -1;
|
||||
this.out.startPacket(this);
|
||||
this.out.writeInt8(0x19);
|
||||
this.out.writeInt32(this.statementId);
|
||||
this.out.flushBuffer(true);
|
||||
}
|
||||
this.sending = false;
|
||||
this.emit('send_end');
|
||||
|
||||
if (this.packet.haveErrorResponse) {
|
||||
this.packet = null;
|
||||
this.resolve = null;
|
||||
this.onPacketReceive = null;
|
||||
this._columns = null;
|
||||
this._rows = null;
|
||||
process.nextTick(this.reject, this.firstError);
|
||||
this.reject = null;
|
||||
this.emit('end', this.firstError);
|
||||
} else {
|
||||
this.packet = null;
|
||||
let totalAffectedRows = 0;
|
||||
this._rows.forEach((row) => {
|
||||
totalAffectedRows += row.affectedRows;
|
||||
});
|
||||
|
||||
const rs = {
|
||||
affectedRows: totalAffectedRows,
|
||||
insertId: this._rows[0].insertId,
|
||||
warningStatus: this._rows[this._rows.length - 1].warningStatus
|
||||
};
|
||||
this.successEnd(rs);
|
||||
this._columns = null;
|
||||
this._rows = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.packet.haveErrorResponse) {
|
||||
this._responseIndex++;
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
}
|
||||
}
|
||||
|
||||
throwError(err, info) {
|
||||
this.packet.waitingResponseNo--;
|
||||
this.sending = false;
|
||||
if (this.packet && !this.packet.haveErrorResponse) {
|
||||
if (err.fatal) {
|
||||
this.packet.waitingResponseNo = 0;
|
||||
}
|
||||
if (this.stack) {
|
||||
err = Errors.createError(
|
||||
err.message,
|
||||
err.fatal,
|
||||
info,
|
||||
err.sqlState,
|
||||
err.errno,
|
||||
this.stack,
|
||||
false
|
||||
);
|
||||
}
|
||||
this.firstError = err;
|
||||
this.packet.endedWithError();
|
||||
}
|
||||
|
||||
if (!this.sending && this.packet.waitingResponseNo === 0) {
|
||||
this.resolve = null;
|
||||
|
||||
//send COM_STMT_CLOSE packet
|
||||
if (!err.fatal && this.statementId) {
|
||||
this.sequenceNo = -1;
|
||||
this.compressSequenceNo = -1;
|
||||
this.out.startPacket(this);
|
||||
this.out.writeInt8(0x19);
|
||||
this.out.writeInt32(this.statementId);
|
||||
this.out.flushBuffer(true);
|
||||
}
|
||||
this.emit('send_end');
|
||||
process.nextTick(this.reject, this.firstError);
|
||||
this.reject = null;
|
||||
this.onPacketReceive = null;
|
||||
this.emit('end', this.firstError);
|
||||
} else {
|
||||
this._responseIndex++;
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that parameters exists and are defined.
|
||||
*
|
||||
* @param info connection info
|
||||
* @returns {boolean} return false if any error occur.
|
||||
*/
|
||||
validateParameters(info) {
|
||||
//validate parameter size.
|
||||
for (let r = 0; r < this.values.length; r++) {
|
||||
if (!Array.isArray(this.values[r])) this.values[r] = [this.values[r]];
|
||||
|
||||
//validate parameter is defined.
|
||||
for (let i = 0; i < this.values[r].length; i++) {
|
||||
if (this.values[r][i] === undefined) {
|
||||
this.emit('send_end');
|
||||
this.throwNewError(
|
||||
'Parameter at position ' +
|
||||
(i + 1) +
|
||||
' is undefined for values ' +
|
||||
r +
|
||||
'\n' +
|
||||
this.displaySql(),
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_PARAMETER_UNDEFINED
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BatchBulk;
|
||||
370
node_modules/mariadb/lib/cmd/batch-rewrite.js
generated
vendored
Normal file
370
node_modules/mariadb/lib/cmd/batch-rewrite.js
generated
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
'use strict';
|
||||
|
||||
const CommonText = require('./common-text-cmd');
|
||||
const Errors = require('../misc/errors');
|
||||
const Parse = require('../misc/parse');
|
||||
const RewritePacket = require('../io/rewrite-packet');
|
||||
const QUOTE = 0x27;
|
||||
|
||||
/**
|
||||
* Protocol COM_QUERY
|
||||
* see : https://mariadb.com/kb/en/library/com_query/
|
||||
*/
|
||||
class BatchRewrite extends CommonText {
|
||||
constructor(resolve, reject, options, connOpts, sql, values) {
|
||||
super(resolve, reject, options, connOpts, sql, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send COM_QUERY
|
||||
*
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
*/
|
||||
start(out, opts, info) {
|
||||
this.sending = true;
|
||||
this.info = info;
|
||||
if (this.opts.timeout) {
|
||||
const err = Errors.createError(
|
||||
'Cannot use timeout for Batch statement',
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_TIMEOUT_NOT_SUPPORTED
|
||||
);
|
||||
this.emit('send_end');
|
||||
this.throwError(err, info);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.initialValues.length === 0) this.initialValues = [[]];
|
||||
if (this.opts.namedPlaceholders) {
|
||||
this.parseResults = Parse.splitRewritableNamedParameterQuery(this.sql, this.initialValues);
|
||||
this.values = this.parseResults.values;
|
||||
} else {
|
||||
this.parseResults = Parse.splitRewritableQuery(this.sql);
|
||||
this.values = this.initialValues;
|
||||
if (!this.validateParameters(info)) {
|
||||
this.sending = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
out.startPacket(this);
|
||||
this.packet = new RewritePacket(
|
||||
this.opts.maxAllowedPacket,
|
||||
out,
|
||||
this.parseResults.partList[0],
|
||||
this.parseResults.partList[this.parseResults.partList.length - 1]
|
||||
);
|
||||
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
this.valueIdx = 0;
|
||||
this.sendQueries();
|
||||
}
|
||||
|
||||
sendQueries() {
|
||||
let flushed = false;
|
||||
while (!flushed && this.sending && this.valueIdx < this.values.length) {
|
||||
this.valueRow = this.values[this.valueIdx++];
|
||||
|
||||
//********************************************
|
||||
// send params
|
||||
//********************************************
|
||||
const len = this.parseResults.partList.length - 3;
|
||||
for (let i = 0; i < len; i++) {
|
||||
const value = this.valueRow[i];
|
||||
flushed = this.packet.writeString(this.parseResults.partList[i + 1]) || flushed;
|
||||
if (value === null) {
|
||||
flushed = this.packet.writeStringAscii('NULL') || flushed;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof value === 'object' &&
|
||||
typeof value.pipe === 'function' &&
|
||||
typeof value.read === 'function'
|
||||
) {
|
||||
//********************************************
|
||||
// param is stream,
|
||||
// now all params will be written by event
|
||||
//********************************************
|
||||
this.registerStreamSendEvent(this.packet, this.info);
|
||||
this.currentParam = i;
|
||||
this.packet.writeInt8(QUOTE); //'
|
||||
|
||||
value.on(
|
||||
'data',
|
||||
function (chunk) {
|
||||
this.packet.writeBufferEscape(chunk);
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
value.on(
|
||||
'end',
|
||||
function () {
|
||||
this.packet.writeInt8(QUOTE); //'
|
||||
this.currentParam++;
|
||||
this.paramWritten();
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
return;
|
||||
} else {
|
||||
//********************************************
|
||||
// param isn't stream. directly write in buffer
|
||||
//********************************************
|
||||
flushed = this.writeParam(this.packet, value, this.opts, this.info) || flushed;
|
||||
}
|
||||
}
|
||||
this.packet.writeString(this.parseResults.partList[this.parseResults.partList.length - 2]);
|
||||
this.packet.mark(!this.parseResults.reWritable || this.valueIdx === this.values.length);
|
||||
}
|
||||
|
||||
if (this.valueIdx < this.values.length && !this.packet.haveErrorResponse) {
|
||||
//there is still data to send
|
||||
setImmediate(this.sendQueries.bind(this));
|
||||
} else {
|
||||
if (this.sending && this.valueIdx === this.values.length) this.emit('send_end');
|
||||
this.sending = false;
|
||||
}
|
||||
}
|
||||
|
||||
displaySql() {
|
||||
if (this.opts && this.initialValues) {
|
||||
if (this.sql.length > this.opts.debugLen) {
|
||||
return 'sql: ' + this.sql.substring(0, this.opts.debugLen) + '...';
|
||||
}
|
||||
|
||||
let sqlMsg = 'sql: ' + this.sql + ' - parameters:';
|
||||
sqlMsg += '[';
|
||||
for (let i = 0; i < this.initialValues.length; i++) {
|
||||
if (i !== 0) sqlMsg += ',';
|
||||
let param = this.initialValues[i];
|
||||
sqlMsg = this.logParameters(sqlMsg, param);
|
||||
if (sqlMsg.length > this.opts.debugLen) {
|
||||
sqlMsg = sqlMsg.substr(0, this.opts.debugLen) + '...';
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlMsg += ']';
|
||||
return sqlMsg;
|
||||
}
|
||||
return 'sql: ' + this.sql + ' - parameters:[]';
|
||||
}
|
||||
|
||||
success(val) {
|
||||
this.packet.waitingResponseNo--;
|
||||
|
||||
if (this.packet.haveErrorResponse) {
|
||||
if (!this.sending && this.packet.waitingResponseNo === 0) {
|
||||
this.packet = null;
|
||||
this.onPacketReceive = null;
|
||||
this.resolve = null;
|
||||
this._columns = null;
|
||||
this._rows = null;
|
||||
process.nextTick(this.reject, this.firstError);
|
||||
this.reject = null;
|
||||
this.emit('end', this.firstError);
|
||||
}
|
||||
} else {
|
||||
if (!this.sending && this.packet.waitingResponseNo === 0) {
|
||||
if (this.parseResults.reWritable) {
|
||||
this.packet = null;
|
||||
let totalAffectedRows = 0;
|
||||
this._rows.forEach((row) => {
|
||||
totalAffectedRows += row.affectedRows;
|
||||
});
|
||||
|
||||
const rs = {
|
||||
affectedRows: totalAffectedRows,
|
||||
insertId: this._rows[0].insertId,
|
||||
warningStatus: this._rows[this._rows.length - 1].warningStatus
|
||||
};
|
||||
this.successEnd(rs);
|
||||
return;
|
||||
} else {
|
||||
this.successEnd(this._rows);
|
||||
}
|
||||
this._columns = null;
|
||||
this._rows = null;
|
||||
return;
|
||||
}
|
||||
this._responseIndex++;
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
}
|
||||
}
|
||||
|
||||
throwError(err, info) {
|
||||
this.packet.waitingResponseNo--;
|
||||
this.sending = false;
|
||||
|
||||
if (this.packet && !this.packet.haveErrorResponse) {
|
||||
if (err.fatal) {
|
||||
this.packet.waitingResponseNo = 0;
|
||||
}
|
||||
if (this.stack) {
|
||||
err = Errors.createError(
|
||||
err.message,
|
||||
err.fatal,
|
||||
info,
|
||||
err.sqlState,
|
||||
err.errno,
|
||||
this.stack,
|
||||
false
|
||||
);
|
||||
}
|
||||
this.firstError = err;
|
||||
this.packet.endedWithError();
|
||||
}
|
||||
|
||||
if (!this.sending && this.packet.waitingResponseNo === 0) {
|
||||
this.packet = null;
|
||||
this.onPacketReceive = null;
|
||||
this.resolve = null;
|
||||
process.nextTick(this.reject, this.firstError);
|
||||
this.reject = null;
|
||||
this.emit('end', this.firstError);
|
||||
} else {
|
||||
this._responseIndex++;
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that parameters exists and are defined.
|
||||
*
|
||||
* @param info connection info
|
||||
* @returns {boolean} return false if any error occur.
|
||||
*/
|
||||
validateParameters(info) {
|
||||
//validate parameter size.
|
||||
for (let r = 0; r < this.values.length; r++) {
|
||||
let val = this.values[r];
|
||||
if (!Array.isArray(val)) {
|
||||
val = [val];
|
||||
this.values[r] = val;
|
||||
}
|
||||
|
||||
if (this.parseResults.partList.length - 3 > val.length) {
|
||||
this.emit('send_end');
|
||||
this.throwNewError(
|
||||
'Parameter at position ' +
|
||||
val.length +
|
||||
' is not set for values ' +
|
||||
r +
|
||||
'\n' +
|
||||
this.displaySql(),
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_MISSING_PARAMETER
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
//validate parameter is defined.
|
||||
for (let i = 0; i < this.parseResults.partList.length - 3; i++) {
|
||||
if (val[i] === undefined) {
|
||||
this.emit('send_end');
|
||||
this.throwNewError(
|
||||
'Parameter at position ' +
|
||||
(i + 1) +
|
||||
' is undefined for values ' +
|
||||
r +
|
||||
'\n' +
|
||||
this.displaySql(),
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_PARAMETER_UNDEFINED
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define params events.
|
||||
* Each parameter indicate that he is written to socket,
|
||||
* emitting event so next parameter can be written.
|
||||
*/
|
||||
registerStreamSendEvent(packet, info) {
|
||||
this.paramWritten = function () {
|
||||
let flushed = false;
|
||||
while (!flushed) {
|
||||
if (this.packet.haveErrorResponse) {
|
||||
this.sending = false;
|
||||
this.emit('send_end');
|
||||
return;
|
||||
}
|
||||
if (this.currentParam === this.valueRow.length) {
|
||||
// all parameters from row are written.
|
||||
flushed =
|
||||
packet.writeString(this.parseResults.partList[this.parseResults.partList.length - 2]) ||
|
||||
flushed;
|
||||
flushed =
|
||||
packet.mark(!this.parseResults.reWritable || this.valueIdx === this.values.length) ||
|
||||
flushed;
|
||||
if (this.valueIdx < this.values.length) {
|
||||
// still remaining rows
|
||||
this.valueRow = this.values[this.valueIdx++];
|
||||
this.currentParam = 0;
|
||||
} else {
|
||||
// all rows are written
|
||||
this.sending = false;
|
||||
this.emit('send_end');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
flushed = packet.writeString(this.parseResults.partList[this.currentParam + 1]) || flushed;
|
||||
const value = this.valueRow[this.currentParam];
|
||||
|
||||
if (value === null) {
|
||||
flushed = packet.writeStringAscii('NULL') || flushed;
|
||||
this.currentParam++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof value === 'object' &&
|
||||
typeof value.pipe === 'function' &&
|
||||
typeof value.read === 'function'
|
||||
) {
|
||||
//********************************************
|
||||
// param is stream,
|
||||
//********************************************
|
||||
flushed = packet.writeInt8(QUOTE) || flushed;
|
||||
value.once(
|
||||
'end',
|
||||
function () {
|
||||
packet.writeInt8(QUOTE);
|
||||
this.currentParam++;
|
||||
this.paramWritten();
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
value.on('data', function (chunk) {
|
||||
packet.writeBufferEscape(chunk);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
// param isn't stream. directly write in buffer
|
||||
//********************************************
|
||||
flushed = this.writeParam(packet, value, this.opts, info) || flushed;
|
||||
this.currentParam++;
|
||||
}
|
||||
|
||||
if (this.sending) setImmediate(this.paramWritten.bind(this));
|
||||
}.bind(this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BatchRewrite;
|
||||
149
node_modules/mariadb/lib/cmd/change-user.js
generated
vendored
Normal file
149
node_modules/mariadb/lib/cmd/change-user.js
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
'use strict';
|
||||
|
||||
const Iconv = require('iconv-lite');
|
||||
const Capabilities = require('../const/capabilities');
|
||||
const Ed25519PasswordAuth = require('./handshake/auth/ed25519-password-auth');
|
||||
const NativePasswordAuth = require('./handshake/auth/native-password-auth');
|
||||
const Collations = require('../const/collations');
|
||||
const Handshake = require('./handshake/handshake');
|
||||
|
||||
/**
|
||||
* send a COM_CHANGE_USER: resets the connection and re-authenticates with the given credentials
|
||||
* see https://mariadb.com/kb/en/library/com_change_user/
|
||||
*/
|
||||
class ChangeUser extends Handshake {
|
||||
constructor(options, resolve, reject, addCommand) {
|
||||
super(resolve, reject, () => {}, addCommand);
|
||||
this.opts = options;
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
this.configAssign(opts, this.opts);
|
||||
let authToken;
|
||||
const pwd = Array.isArray(this.opts.password) ? this.opts.password[0] : this.opts.password;
|
||||
switch (info.defaultPluginName) {
|
||||
case 'mysql_native_password':
|
||||
case '':
|
||||
authToken = NativePasswordAuth.encryptPassword(pwd, info.seed, 'sha1');
|
||||
break;
|
||||
case 'client_ed25519':
|
||||
authToken = Ed25519PasswordAuth.encryptPassword(pwd, info.seed);
|
||||
break;
|
||||
default:
|
||||
authToken = Buffer.alloc(0);
|
||||
break;
|
||||
}
|
||||
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x11);
|
||||
out.writeString(this.opts.user || '');
|
||||
out.writeInt8(0);
|
||||
|
||||
if (info.serverCapabilities & Capabilities.SECURE_CONNECTION) {
|
||||
out.writeInt8(authToken.length);
|
||||
out.writeBuffer(authToken, 0, authToken.length);
|
||||
} else {
|
||||
out.writeBuffer(authToken, 0, authToken.length);
|
||||
out.writeInt8(0);
|
||||
}
|
||||
|
||||
if (info.clientCapabilities & Capabilities.CONNECT_WITH_DB) {
|
||||
out.writeString(this.opts.database);
|
||||
out.writeInt8(0);
|
||||
info.database = this.opts.database;
|
||||
}
|
||||
|
||||
out.writeInt16(this.opts.collation.index);
|
||||
|
||||
if (info.clientCapabilities & Capabilities.PLUGIN_AUTH) {
|
||||
out.writeString(info.defaultPluginName);
|
||||
out.writeInt8(0);
|
||||
}
|
||||
|
||||
if (info.clientCapabilities & Capabilities.CONNECT_ATTRS) {
|
||||
out.writeInt8(0xfc);
|
||||
let initPos = out.pos; //save position, assuming connection attributes length will be less than 2 bytes length
|
||||
out.writeInt16(0);
|
||||
|
||||
const encoding = this.opts.collation.charset;
|
||||
|
||||
writeParam(out, '_client_name', encoding);
|
||||
writeParam(out, 'MariaDB connector/Node', encoding);
|
||||
|
||||
let packageJson = require('../../package.json');
|
||||
writeParam(out, '_client_version', encoding);
|
||||
writeParam(out, packageJson.version, encoding);
|
||||
|
||||
writeParam(out, '_node_version', encoding);
|
||||
writeParam(out, process.versions.node, encoding);
|
||||
|
||||
if (opts.connectAttributes !== true) {
|
||||
let attrNames = Object.keys(this.opts.connectAttributes);
|
||||
for (let k = 0; k < attrNames.length; ++k) {
|
||||
writeParam(out, attrNames[k], encoding);
|
||||
writeParam(out, this.opts.connectAttributes[attrNames[k]], encoding);
|
||||
}
|
||||
}
|
||||
|
||||
//write end size
|
||||
out.writeInt16AtPos(initPos);
|
||||
}
|
||||
|
||||
out.flushBuffer(true);
|
||||
this.onPacketReceive = this.handshakeResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign global configuration option used by result-set to current query option.
|
||||
* a little faster than Object.assign() since doest copy all information
|
||||
*
|
||||
* @param connOpts connection global configuration
|
||||
* @param opt current options
|
||||
*/
|
||||
configAssign(connOpts, opt) {
|
||||
if (!opt) {
|
||||
this.opts = connOpts;
|
||||
return;
|
||||
}
|
||||
this.opts.database = opt.database ? opt.database : connOpts.database;
|
||||
this.opts.connectAttributes = opt.connectAttributes
|
||||
? opt.connectAttributes
|
||||
: connOpts.connectAttributes;
|
||||
|
||||
if (opt.charset && typeof opt.charset === 'string') {
|
||||
this.opts.collation = Collations.fromCharset(opt.charset.toLowerCase());
|
||||
if (this.opts.collation === undefined) {
|
||||
this.opts.collation = Collations.fromName(opt.charset.toUpperCase());
|
||||
if (this.opts.collation !== undefined) {
|
||||
console.log(
|
||||
"warning: please use option 'collation' " +
|
||||
"in replacement of 'charset' when using a collation name ('" +
|
||||
opt.charset +
|
||||
"')\n" +
|
||||
"(collation looks like 'UTF8MB4_UNICODE_CI', charset like 'utf8')."
|
||||
);
|
||||
}
|
||||
}
|
||||
if (this.opts.collation === undefined)
|
||||
throw new RangeError("Unknown charset '" + opt.charset + "'");
|
||||
} else if (opt.collation && typeof opt.collation === 'string') {
|
||||
const initial = opt.collation;
|
||||
this.opts.collation = Collations.fromName(initial.toUpperCase());
|
||||
if (this.opts.collation === undefined)
|
||||
throw new RangeError("Unknown collation '" + initial + "'");
|
||||
} else {
|
||||
this.opts.collation = Collations.fromIndex(opt.charsetNumber) || connOpts.collation;
|
||||
}
|
||||
connOpts.password = opt.password;
|
||||
}
|
||||
}
|
||||
|
||||
function writeParam(out, val, encoding) {
|
||||
let param = Buffer.isEncoding(encoding)
|
||||
? Buffer.from(val, encoding)
|
||||
: Iconv.encode(val, encoding);
|
||||
out.writeLengthCoded(param.length);
|
||||
out.writeBuffer(param, 0, param.length);
|
||||
}
|
||||
|
||||
module.exports = ChangeUser;
|
||||
17
node_modules/mariadb/lib/cmd/class/ok-packet.js
generated
vendored
Normal file
17
node_modules/mariadb/lib/cmd/class/ok-packet.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const Command = require('../command');
|
||||
|
||||
/**
|
||||
* Ok_Packet
|
||||
* see https://mariadb.com/kb/en/ok_packet/
|
||||
*/
|
||||
class OkPacket {
|
||||
constructor(affectedRows, insertId, warningStatus) {
|
||||
this.affectedRows = affectedRows;
|
||||
this.insertId = insertId;
|
||||
this.warningStatus = warningStatus;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = OkPacket;
|
||||
102
node_modules/mariadb/lib/cmd/column-definition.js
generated
vendored
Normal file
102
node_modules/mariadb/lib/cmd/column-definition.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
'use strict';
|
||||
|
||||
const Collations = require('../const/collations.js');
|
||||
const FieldType = require('../const/field-type');
|
||||
const Capabilities = require('../const/capabilities');
|
||||
|
||||
/**
|
||||
* Column definition
|
||||
* see https://mariadb.com/kb/en/library/resultset/#column-definition-packet
|
||||
*/
|
||||
class ColumnDef {
|
||||
constructor(packet, info) {
|
||||
this._parse = new StringParser(packet);
|
||||
if (info.serverCapabilities & Capabilities.MARIADB_CLIENT_EXTENDED_TYPE_INFO) {
|
||||
const subPacket = packet.subPacketLengthEncoded();
|
||||
while (subPacket.remaining()) {
|
||||
switch (subPacket.readUInt8()) {
|
||||
case 0:
|
||||
this.dataTypeName = subPacket.readAsciiStringLengthEncoded();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
this.dataTypeFormat = subPacket.readAsciiStringLengthEncoded();
|
||||
break;
|
||||
|
||||
default:
|
||||
// skip data
|
||||
const len = subPacket.readUnsignedLength();
|
||||
if (len) {
|
||||
subPacket.skip(len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
packet.skip(1); // length of fixed fields
|
||||
this.collation = Collations.fromIndex(packet.readUInt16());
|
||||
this.columnLength = packet.readUInt32();
|
||||
this.columnType = packet.readUInt8();
|
||||
this.flags = packet.readUInt16();
|
||||
this.scale = packet.readUInt8();
|
||||
this.type = FieldType.TYPES[this.columnType];
|
||||
}
|
||||
|
||||
db() {
|
||||
return this._parse.packet.readString(this._parse.dbOffset, this._parse.dbLength);
|
||||
}
|
||||
|
||||
schema() {
|
||||
return this._parse.packet.readString(this._parse.dbOffset, this._parse.dbLength);
|
||||
}
|
||||
|
||||
table() {
|
||||
return this._parse.packet.readString(this._parse.tableOffset, this._parse.tableLength);
|
||||
}
|
||||
|
||||
orgTable() {
|
||||
return this._parse.packet.readString(this._parse.orgTableOffset, this._parse.orgTableLength);
|
||||
}
|
||||
|
||||
name() {
|
||||
return this._parse.packet.readString(this._parse.nameOffset, this._parse.nameLength);
|
||||
}
|
||||
|
||||
orgName() {
|
||||
return this._parse.packet.readString(this._parse.orgNameOffset, this._parse.orgNameLength);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String parser.
|
||||
* This object permits to avoid listing all private information to metadata object.
|
||||
*/
|
||||
class StringParser {
|
||||
constructor(packet) {
|
||||
packet.skip(4); // skip 'def'
|
||||
|
||||
this.dbLength = packet.readUnsignedLength();
|
||||
this.dbOffset = packet.pos;
|
||||
packet.skip(this.dbLength);
|
||||
|
||||
this.tableLength = packet.readUnsignedLength();
|
||||
this.tableOffset = packet.pos;
|
||||
packet.skip(this.tableLength);
|
||||
|
||||
this.orgTableLength = packet.readUnsignedLength();
|
||||
this.orgTableOffset = packet.pos;
|
||||
packet.skip(this.orgTableLength);
|
||||
|
||||
this.nameLength = packet.readUnsignedLength();
|
||||
this.nameOffset = packet.pos;
|
||||
packet.skip(this.nameLength);
|
||||
|
||||
this.orgNameLength = packet.readUnsignedLength();
|
||||
this.orgNameOffset = packet.pos;
|
||||
packet.skip(this.orgNameLength);
|
||||
this.packet = packet;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ColumnDef;
|
||||
165
node_modules/mariadb/lib/cmd/command.js
generated
vendored
Normal file
165
node_modules/mariadb/lib/cmd/command.js
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const Errors = require('../misc/errors');
|
||||
const ServerStatus = require('../const/server-status');
|
||||
const StateChange = require('../const/state-change');
|
||||
const Collations = require('../const/collations');
|
||||
const OkPacket = require('./class/ok-packet');
|
||||
|
||||
/**
|
||||
* Default command interface.
|
||||
*/
|
||||
class Command extends EventEmitter {
|
||||
constructor(resolve, reject) {
|
||||
super();
|
||||
this.sequenceNo = -1;
|
||||
this.compressSequenceNo = -1;
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
this.sending = false;
|
||||
}
|
||||
|
||||
displaySql() {}
|
||||
|
||||
/**
|
||||
* Throw an an unexpected error.
|
||||
* server exchange will still be read to keep connection in a good state, but promise will be rejected.
|
||||
*
|
||||
* @param msg message
|
||||
* @param fatal is error fatal for connection
|
||||
* @param info current server state information
|
||||
* @param sqlState error sqlState
|
||||
* @param errno error number
|
||||
*/
|
||||
throwUnexpectedError(msg, fatal, info, sqlState, errno) {
|
||||
if (this.reject) {
|
||||
process.nextTick(
|
||||
this.reject,
|
||||
Errors.createError(msg, fatal, info, sqlState, errno, this.stack, false)
|
||||
);
|
||||
this.resolve = null;
|
||||
this.reject = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and throw new Error from error information
|
||||
* only first called throwing an error or successfully end will be executed.
|
||||
*
|
||||
* @param msg message
|
||||
* @param fatal is error fatal for connection
|
||||
* @param info current server state information
|
||||
* @param sqlState error sqlState
|
||||
* @param errno error number
|
||||
*/
|
||||
throwNewError(msg, fatal, info, sqlState, errno) {
|
||||
this.onPacketReceive = null;
|
||||
if (this.reject) {
|
||||
process.nextTick(
|
||||
this.reject,
|
||||
Errors.createError(msg, fatal, info, sqlState, errno, this.stack, false)
|
||||
);
|
||||
this.resolve = null;
|
||||
this.reject = null;
|
||||
}
|
||||
this.emit('end');
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw Error
|
||||
* only first called throwing an error or successfully end will be executed.
|
||||
*
|
||||
* @param err error to be thrown
|
||||
* @param info current server state information
|
||||
*/
|
||||
throwError(err, info) {
|
||||
this.onPacketReceive = null;
|
||||
if (this.reject) {
|
||||
if (this.stack) {
|
||||
err = Errors.createError(
|
||||
err.message,
|
||||
err.fatal,
|
||||
info,
|
||||
err.sqlState,
|
||||
err.errno,
|
||||
this.stack,
|
||||
false
|
||||
);
|
||||
}
|
||||
this.resolve = null;
|
||||
process.nextTick(this.reject, err);
|
||||
this.reject = null;
|
||||
}
|
||||
this.emit('end', err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Successfully end command.
|
||||
* only first called throwing an error or successfully end will be executed.
|
||||
*
|
||||
* @param val return value.
|
||||
*/
|
||||
successEnd(val) {
|
||||
this.onPacketReceive = null;
|
||||
if (this.resolve) {
|
||||
this.reject = null;
|
||||
process.nextTick(this.resolve, val);
|
||||
this.resolve = null;
|
||||
}
|
||||
this.emit('end');
|
||||
}
|
||||
|
||||
static parseOkPacket(packet, out, opts, info) {
|
||||
packet.skip(1); //skip header
|
||||
|
||||
const affectedRows = packet.readUnsignedLength();
|
||||
const insertId = opts.supportBigInt
|
||||
? packet.readSignedLengthBigInt()
|
||||
: packet.readSignedLength();
|
||||
|
||||
info.status = packet.readUInt16();
|
||||
|
||||
const okPacket = new OkPacket(affectedRows, insertId, packet.readUInt16());
|
||||
|
||||
if (info.status & ServerStatus.SESSION_STATE_CHANGED) {
|
||||
packet.skipLengthCodedNumber();
|
||||
while (packet.remaining()) {
|
||||
const subPacket = packet.subPacketLengthEncoded();
|
||||
while (subPacket.remaining()) {
|
||||
const type = subPacket.readUInt8();
|
||||
switch (type) {
|
||||
case StateChange.SESSION_TRACK_SYSTEM_VARIABLES:
|
||||
const subSubPacket = subPacket.subPacketLengthEncoded();
|
||||
const variable = subSubPacket.readStringLength();
|
||||
const value = subSubPacket.readStringLength();
|
||||
|
||||
switch (variable) {
|
||||
case 'character_set_client':
|
||||
opts.collation = Collations.fromCharset(value);
|
||||
if (opts.collation === undefined) {
|
||||
this.throwError(new Error("unknown charset : '" + value + "'"), info);
|
||||
return;
|
||||
}
|
||||
opts.emit('collation', opts.collation);
|
||||
break;
|
||||
|
||||
default:
|
||||
//variable not used by driver
|
||||
}
|
||||
break;
|
||||
|
||||
case StateChange.SESSION_TRACK_SCHEMA:
|
||||
const subSubPacket2 = subPacket.subPacketLengthEncoded();
|
||||
info.database = subSubPacket2.readStringLength();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return okPacket;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Command;
|
||||
327
node_modules/mariadb/lib/cmd/common-binary-cmd.js
generated
vendored
Normal file
327
node_modules/mariadb/lib/cmd/common-binary-cmd.js
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
'use strict';
|
||||
|
||||
const ResultSet = require('./resultset');
|
||||
|
||||
class CommonBinary extends ResultSet {
|
||||
constructor(resolve, reject, cmdOpts, connOpts, sql, values) {
|
||||
super(resolve, reject);
|
||||
this.configAssign(connOpts, cmdOpts);
|
||||
this.sql = sql;
|
||||
this.initialValues = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write (and escape) current parameter value to output writer
|
||||
*
|
||||
* @param out output writer
|
||||
* @param value current parameter
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
*/
|
||||
writeParam(out, value, opts, info) {
|
||||
let flushed = false;
|
||||
switch (typeof value) {
|
||||
case 'boolean':
|
||||
flushed = out.writeInt8(0x00);
|
||||
flushed = out.writeInt8(value ? 0x01 : 0x00) || flushed;
|
||||
break;
|
||||
case 'bigint':
|
||||
case 'number':
|
||||
flushed = out.writeInt8(0x00);
|
||||
flushed = out.writeLengthStringAscii('' + value) || flushed;
|
||||
break;
|
||||
case 'object':
|
||||
if (Object.prototype.toString.call(value) === '[object Date]') {
|
||||
flushed = out.writeInt8(0x00);
|
||||
flushed = out.writeBinaryDate(value, opts) || flushed;
|
||||
} else if (Buffer.isBuffer(value)) {
|
||||
flushed = out.writeInt8(0x00);
|
||||
flushed = out.writeLengthEncodedBuffer(value) || flushed;
|
||||
} else if (typeof value.toSqlString === 'function') {
|
||||
flushed = out.writeInt8(0x00);
|
||||
flushed = out.writeLengthEncodedString(String(value.toSqlString())) || flushed;
|
||||
} else {
|
||||
if (
|
||||
value.type != null &&
|
||||
[
|
||||
'Point',
|
||||
'LineString',
|
||||
'Polygon',
|
||||
'MultiPoint',
|
||||
'MultiLineString',
|
||||
'MultiPolygon',
|
||||
'GeometryCollection'
|
||||
].includes(value.type)
|
||||
) {
|
||||
const geoBuff = this.getBufferFromGeometryValue(value);
|
||||
if (geoBuff) {
|
||||
flushed = out.writeInt8(0x00); //Value follow
|
||||
flushed =
|
||||
out.writeLengthEncodedBuffer(Buffer.concat([Buffer.from([0, 0, 0, 0]), geoBuff])) ||
|
||||
flushed;
|
||||
} else {
|
||||
flushed = out.writeInt8(0x01); //NULL
|
||||
}
|
||||
} else {
|
||||
//TODO check if permitSetMultiParamEntries is needed !?
|
||||
flushed = out.writeInt8(0x00);
|
||||
flushed = out.writeLengthEncodedString(JSON.stringify(value)) || flushed;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
flushed = out.writeInt8(0x00);
|
||||
flushed = out.writeLengthEncodedString(value) || flushed;
|
||||
}
|
||||
return flushed;
|
||||
}
|
||||
|
||||
getBufferFromGeometryValue(value, headerType) {
|
||||
let geoBuff;
|
||||
let pos;
|
||||
let type;
|
||||
if (!headerType) {
|
||||
switch (value.type) {
|
||||
case 'Point':
|
||||
geoBuff = Buffer.allocUnsafe(21);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(1, 1); //wkbPoint
|
||||
if (
|
||||
value.coordinates &&
|
||||
Array.isArray(value.coordinates) &&
|
||||
value.coordinates.length >= 2 &&
|
||||
!isNaN(value.coordinates[0]) &&
|
||||
!isNaN(value.coordinates[1])
|
||||
) {
|
||||
geoBuff.writeDoubleLE(value.coordinates[0], 5); //X
|
||||
geoBuff.writeDoubleLE(value.coordinates[1], 13); //Y
|
||||
return geoBuff;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
case 'LineString':
|
||||
if (value.coordinates && Array.isArray(value.coordinates)) {
|
||||
const pointNumber = value.coordinates.length;
|
||||
geoBuff = Buffer.allocUnsafe(9 + 16 * pointNumber);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(2, 1); //wkbLineString
|
||||
geoBuff.writeInt32LE(pointNumber, 5);
|
||||
for (let i = 0; i < pointNumber; i++) {
|
||||
if (
|
||||
value.coordinates[i] &&
|
||||
Array.isArray(value.coordinates[i]) &&
|
||||
value.coordinates[i].length >= 2 &&
|
||||
!isNaN(value.coordinates[i][0]) &&
|
||||
!isNaN(value.coordinates[i][1])
|
||||
) {
|
||||
geoBuff.writeDoubleLE(value.coordinates[i][0], 9 + 16 * i); //X
|
||||
geoBuff.writeDoubleLE(value.coordinates[i][1], 17 + 16 * i); //Y
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return geoBuff;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
case 'Polygon':
|
||||
if (value.coordinates && Array.isArray(value.coordinates)) {
|
||||
const numRings = value.coordinates.length;
|
||||
let size = 0;
|
||||
for (let i = 0; i < numRings; i++) {
|
||||
size += 4 + 16 * value.coordinates[i].length;
|
||||
}
|
||||
geoBuff = Buffer.allocUnsafe(9 + size);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(3, 1); //wkbPolygon
|
||||
geoBuff.writeInt32LE(numRings, 5);
|
||||
pos = 9;
|
||||
for (let i = 0; i < numRings; i++) {
|
||||
const lineString = value.coordinates[i];
|
||||
if (lineString && Array.isArray(lineString)) {
|
||||
geoBuff.writeInt32LE(lineString.length, pos);
|
||||
pos += 4;
|
||||
for (let j = 0; j < lineString.length; j++) {
|
||||
if (
|
||||
lineString[j] &&
|
||||
Array.isArray(lineString[j]) &&
|
||||
lineString[j].length >= 2 &&
|
||||
!isNaN(lineString[j][0]) &&
|
||||
!isNaN(lineString[j][1])
|
||||
) {
|
||||
geoBuff.writeDoubleLE(lineString[j][0], pos); //X
|
||||
geoBuff.writeDoubleLE(lineString[j][1], pos + 8); //Y
|
||||
pos += 16;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return geoBuff;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
case 'MultiPoint':
|
||||
type = 'MultiPoint';
|
||||
geoBuff = Buffer.allocUnsafe(9);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(4, 1); //wkbMultiPoint
|
||||
break;
|
||||
|
||||
case 'MultiLineString':
|
||||
type = 'MultiLineString';
|
||||
geoBuff = Buffer.allocUnsafe(9);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(5, 1); //wkbMultiLineString
|
||||
break;
|
||||
|
||||
case 'MultiPolygon':
|
||||
type = 'MultiPolygon';
|
||||
geoBuff = Buffer.allocUnsafe(9);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(6, 1); //wkbMultiPolygon
|
||||
break;
|
||||
|
||||
case 'GeometryCollection':
|
||||
geoBuff = Buffer.allocUnsafe(9);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(7, 1); //wkbGeometryCollection
|
||||
|
||||
if (value.geometries && Array.isArray(value.geometries)) {
|
||||
const coordinateLength = value.geometries.length;
|
||||
const subArrays = [geoBuff];
|
||||
for (let i = 0; i < coordinateLength; i++) {
|
||||
const tmpBuf = this.getBufferFromGeometryValue(value.geometries[i]);
|
||||
if (tmpBuf == null) break;
|
||||
subArrays.push(tmpBuf);
|
||||
}
|
||||
geoBuff.writeInt32LE(subArrays.length - 1, 5);
|
||||
return Buffer.concat(subArrays);
|
||||
} else {
|
||||
geoBuff.writeInt32LE(0, 5);
|
||||
return geoBuff;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
if (value.coordinates && Array.isArray(value.coordinates)) {
|
||||
const coordinateLength = value.coordinates.length;
|
||||
const subArrays = [geoBuff];
|
||||
for (let i = 0; i < coordinateLength; i++) {
|
||||
const tmpBuf = this.getBufferFromGeometryValue(value.coordinates[i], type);
|
||||
if (tmpBuf == null) break;
|
||||
subArrays.push(tmpBuf);
|
||||
}
|
||||
geoBuff.writeInt32LE(subArrays.length - 1, 5);
|
||||
return Buffer.concat(subArrays);
|
||||
} else {
|
||||
geoBuff.writeInt32LE(0, 5);
|
||||
return geoBuff;
|
||||
}
|
||||
} else {
|
||||
switch (headerType) {
|
||||
case 'MultiPoint':
|
||||
if (
|
||||
value &&
|
||||
Array.isArray(value) &&
|
||||
value.length >= 2 &&
|
||||
!isNaN(value[0]) &&
|
||||
!isNaN(value[1])
|
||||
) {
|
||||
geoBuff = Buffer.allocUnsafe(21);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(1, 1); //wkbPoint
|
||||
geoBuff.writeDoubleLE(value[0], 5); //X
|
||||
geoBuff.writeDoubleLE(value[1], 13); //Y
|
||||
return geoBuff;
|
||||
}
|
||||
return null;
|
||||
|
||||
case 'MultiLineString':
|
||||
if (value && Array.isArray(value)) {
|
||||
const pointNumber = value.length;
|
||||
geoBuff = Buffer.allocUnsafe(9 + 16 * pointNumber);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(2, 1); //wkbLineString
|
||||
geoBuff.writeInt32LE(pointNumber, 5);
|
||||
for (let i = 0; i < pointNumber; i++) {
|
||||
if (
|
||||
value[i] &&
|
||||
Array.isArray(value[i]) &&
|
||||
value[i].length >= 2 &&
|
||||
!isNaN(value[i][0]) &&
|
||||
!isNaN(value[i][1])
|
||||
) {
|
||||
geoBuff.writeDoubleLE(value[i][0], 9 + 16 * i); //X
|
||||
geoBuff.writeDoubleLE(value[i][1], 17 + 16 * i); //Y
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return geoBuff;
|
||||
}
|
||||
return null;
|
||||
|
||||
case 'MultiPolygon':
|
||||
if (value && Array.isArray(value)) {
|
||||
const numRings = value.length;
|
||||
let size = 0;
|
||||
for (let i = 0; i < numRings; i++) {
|
||||
size += 4 + 16 * value[i].length;
|
||||
}
|
||||
geoBuff = Buffer.allocUnsafe(9 + size);
|
||||
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
|
||||
geoBuff.writeInt32LE(3, 1); //wkbPolygon
|
||||
geoBuff.writeInt32LE(numRings, 5);
|
||||
pos = 9;
|
||||
for (let i = 0; i < numRings; i++) {
|
||||
const lineString = value[i];
|
||||
if (lineString && Array.isArray(lineString)) {
|
||||
geoBuff.writeInt32LE(lineString.length, pos);
|
||||
pos += 4;
|
||||
for (let j = 0; j < lineString.length; j++) {
|
||||
if (
|
||||
lineString[j] &&
|
||||
Array.isArray(lineString[j]) &&
|
||||
lineString[j].length >= 2 &&
|
||||
!isNaN(lineString[j][0]) &&
|
||||
!isNaN(lineString[j][1])
|
||||
) {
|
||||
geoBuff.writeDoubleLE(lineString[j][0], pos); //X
|
||||
geoBuff.writeDoubleLE(lineString[j][1], pos + 8); //Y
|
||||
pos += 16;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return geoBuff;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read text result-set row
|
||||
*
|
||||
* see: https://mariadb.com/kb/en/library/resultset-row/#text-resultset-row
|
||||
* data are created according to their type.
|
||||
*
|
||||
* @param columns columns metadata
|
||||
* @param packet current row packet
|
||||
* @param connOpts connection options
|
||||
* @returns {*} row data
|
||||
*/
|
||||
parseRow(columns, packet, connOpts) {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CommonBinary;
|
||||
427
node_modules/mariadb/lib/cmd/common-text-cmd.js
generated
vendored
Normal file
427
node_modules/mariadb/lib/cmd/common-text-cmd.js
generated
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
'use strict';
|
||||
|
||||
const ResultSet = require('./resultset');
|
||||
const FieldDetail = require('../const/field-detail');
|
||||
const FieldType = require('../const/field-type');
|
||||
const Long = require('long');
|
||||
const moment = require('moment-timezone');
|
||||
const QUOTE = 0x27;
|
||||
|
||||
class CommonText extends ResultSet {
|
||||
constructor(resolve, reject, cmdOpts, connOpts, sql, values) {
|
||||
super(resolve, reject);
|
||||
this.configAssign(connOpts, cmdOpts);
|
||||
this.sql = sql;
|
||||
this.initialValues = values;
|
||||
this.getDateQuote = this.opts.tz
|
||||
? this.opts.tz === 'Etc/UTC'
|
||||
? CommonText.getUtcDate
|
||||
: CommonText.getTimezoneDate
|
||||
: CommonText.getLocalDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write (and escape) current parameter value to output writer
|
||||
*
|
||||
* @param out output writer
|
||||
* @param value current parameter
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
*/
|
||||
writeParam(out, value, opts, info) {
|
||||
switch (typeof value) {
|
||||
case 'boolean':
|
||||
out.writeStringAscii(value ? 'true' : 'false');
|
||||
break;
|
||||
case 'bigint':
|
||||
case 'number':
|
||||
out.writeStringAscii('' + value);
|
||||
break;
|
||||
case 'object':
|
||||
if (value === null) {
|
||||
out.writeStringAscii('NULL');
|
||||
} else if (Object.prototype.toString.call(value) === '[object Date]') {
|
||||
out.writeStringAscii(this.getDateQuote(value, opts));
|
||||
} else if (Buffer.isBuffer(value)) {
|
||||
out.writeStringAscii("_BINARY '");
|
||||
out.writeBufferEscape(value);
|
||||
out.writeInt8(QUOTE);
|
||||
} else if (typeof value.toSqlString === 'function') {
|
||||
out.writeStringEscapeQuote(String(value.toSqlString()));
|
||||
} else if (Long.isLong(value)) {
|
||||
out.writeStringAscii(value.toString());
|
||||
} else if (Array.isArray(value)) {
|
||||
if (opts.arrayParenthesis) {
|
||||
out.writeStringAscii('(');
|
||||
}
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (i !== 0) out.writeStringAscii(',');
|
||||
this.writeParam(out, value[i], opts, info);
|
||||
}
|
||||
if (opts.arrayParenthesis) {
|
||||
out.writeStringAscii(')');
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
value.type != null &&
|
||||
[
|
||||
'Point',
|
||||
'LineString',
|
||||
'Polygon',
|
||||
'MultiPoint',
|
||||
'MultiLineString',
|
||||
'MultiPolygon',
|
||||
'GeometryCollection'
|
||||
].includes(value.type)
|
||||
) {
|
||||
//GeoJSON format.
|
||||
let prefix =
|
||||
(info.isMariaDB() && info.hasMinVersion(10, 1, 4)) ||
|
||||
(!info.isMariaDB() && info.hasMinVersion(5, 7, 6))
|
||||
? 'ST_'
|
||||
: '';
|
||||
switch (value.type) {
|
||||
case 'Point':
|
||||
out.writeStringAscii(
|
||||
prefix +
|
||||
"PointFromText('POINT(" +
|
||||
CommonText.geoPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
break;
|
||||
|
||||
case 'LineString':
|
||||
out.writeStringAscii(
|
||||
prefix +
|
||||
"LineFromText('LINESTRING(" +
|
||||
CommonText.geoArrayPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
break;
|
||||
|
||||
case 'Polygon':
|
||||
out.writeStringAscii(
|
||||
prefix +
|
||||
"PolygonFromText('POLYGON(" +
|
||||
CommonText.geoMultiArrayPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
break;
|
||||
|
||||
case 'MultiPoint':
|
||||
out.writeStringAscii(
|
||||
prefix +
|
||||
"MULTIPOINTFROMTEXT('MULTIPOINT(" +
|
||||
CommonText.geoArrayPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
break;
|
||||
|
||||
case 'MultiLineString':
|
||||
out.writeStringAscii(
|
||||
prefix +
|
||||
"MLineFromText('MULTILINESTRING(" +
|
||||
CommonText.geoMultiArrayPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
break;
|
||||
|
||||
case 'MultiPolygon':
|
||||
out.writeStringAscii(
|
||||
prefix +
|
||||
"MPolyFromText('MULTIPOLYGON(" +
|
||||
CommonText.geoMultiPolygonToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
break;
|
||||
|
||||
case 'GeometryCollection':
|
||||
out.writeStringAscii(
|
||||
prefix +
|
||||
"GeomCollFromText('GEOMETRYCOLLECTION(" +
|
||||
CommonText.geometricCollectionToString(value.geometries) +
|
||||
")')"
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (opts.permitSetMultiParamEntries) {
|
||||
let first = true;
|
||||
for (let key in value) {
|
||||
const val = value[key];
|
||||
if (typeof val === 'function') continue;
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
out.writeStringAscii(',');
|
||||
}
|
||||
out.writeString('`' + key + '`');
|
||||
out.writeStringAscii('=');
|
||||
this.writeParam(out, val, opts, info);
|
||||
}
|
||||
if (first) out.writeStringEscapeQuote(JSON.stringify(value));
|
||||
} else {
|
||||
out.writeStringEscapeQuote(JSON.stringify(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
out.writeStringEscapeQuote(value);
|
||||
}
|
||||
}
|
||||
|
||||
static geometricCollectionToString(geo) {
|
||||
if (!geo) return '';
|
||||
let st = '';
|
||||
for (let i = 0; i < geo.length; i++) {
|
||||
//GeoJSON format.
|
||||
st += i !== 0 ? ',' : '';
|
||||
switch (geo[i].type) {
|
||||
case 'Point':
|
||||
st += 'POINT(' + CommonText.geoPointToString(geo[i].coordinates) + ')';
|
||||
break;
|
||||
|
||||
case 'LineString':
|
||||
st += 'LINESTRING(' + CommonText.geoArrayPointToString(geo[i].coordinates) + ')';
|
||||
break;
|
||||
|
||||
case 'Polygon':
|
||||
st += 'POLYGON(' + CommonText.geoMultiArrayPointToString(geo[i].coordinates) + ')';
|
||||
break;
|
||||
|
||||
case 'MultiPoint':
|
||||
st += 'MULTIPOINT(' + CommonText.geoArrayPointToString(geo[i].coordinates) + ')';
|
||||
break;
|
||||
|
||||
case 'MultiLineString':
|
||||
st +=
|
||||
'MULTILINESTRING(' + CommonText.geoMultiArrayPointToString(geo[i].coordinates) + ')';
|
||||
break;
|
||||
|
||||
case 'MultiPolygon':
|
||||
st += 'MULTIPOLYGON(' + CommonText.geoMultiPolygonToString(geo[i].coordinates) + ')';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
static geoMultiPolygonToString(coords) {
|
||||
if (!coords) return '';
|
||||
let st = '';
|
||||
for (let i = 0; i < coords.length; i++) {
|
||||
st += (i !== 0 ? ',(' : '(') + CommonText.geoMultiArrayPointToString(coords[i]) + ')';
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
static geoMultiArrayPointToString(coords) {
|
||||
if (!coords) return '';
|
||||
let st = '';
|
||||
for (let i = 0; i < coords.length; i++) {
|
||||
st += (i !== 0 ? ',(' : '(') + CommonText.geoArrayPointToString(coords[i]) + ')';
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
static geoArrayPointToString(coords) {
|
||||
if (!coords) return '';
|
||||
let st = '';
|
||||
for (let i = 0; i < coords.length; i++) {
|
||||
st += (i !== 0 ? ',' : '') + CommonText.geoPointToString(coords[i]);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
static geoPointToString(coords) {
|
||||
if (!coords) return '';
|
||||
return (isNaN(coords[0]) ? '' : coords[0]) + ' ' + (isNaN(coords[1]) ? '' : coords[1]);
|
||||
}
|
||||
|
||||
parseRowAsArray(columns, packet, connOpts) {
|
||||
const row = new Array(this._columnCount);
|
||||
for (let i = 0; i < this._columnCount; i++) {
|
||||
row[i] = this._getValue(i, columns[i], this.opts, connOpts, packet);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
parseRowNested(columns, packet, connOpts) {
|
||||
const row = {};
|
||||
for (let i = 0; i < this._columnCount; i++) {
|
||||
if (!row[this.tableHeader[i][0]]) row[this.tableHeader[i][0]] = {};
|
||||
row[this.tableHeader[i][0]][this.tableHeader[i][1]] = this._getValue(
|
||||
i,
|
||||
columns[i],
|
||||
this.opts,
|
||||
connOpts,
|
||||
packet
|
||||
);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
parseRowStd(columns, packet, connOpts) {
|
||||
const row = {};
|
||||
for (let i = 0; i < this._columnCount; i++) {
|
||||
row[this.tableHeader[i]] = this._getValue(i, columns[i], this.opts, connOpts, packet);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
castTextWrapper(column, opts, connOpts, packet) {
|
||||
column.string = () => packet.readStringLength();
|
||||
column.buffer = () => packet.readBufferLengthEncoded();
|
||||
column.float = () => packet.readFloatLengthCoded();
|
||||
column.int = () => packet.readIntLengthEncoded();
|
||||
column.long = () =>
|
||||
packet.readLongLengthEncoded(
|
||||
opts.supportBigInt,
|
||||
opts.supportBigNumbers,
|
||||
opts.bigNumberStrings,
|
||||
(column.flags & FieldDetail.UNSIGNED) > 0
|
||||
);
|
||||
column.decimal = () => packet.readDecimalLengthEncoded(opts.bigNumberStrings);
|
||||
column.date = () => packet.readDateTime(opts);
|
||||
column.geometry = () => {
|
||||
return column.readGeometry();
|
||||
};
|
||||
}
|
||||
|
||||
readCastValue(index, column, opts, connOpts, packet) {
|
||||
this.castTextWrapper(column, opts, connOpts, packet);
|
||||
return opts.typeCast(
|
||||
column,
|
||||
this.readRowData.bind(this, index, column, opts, connOpts, packet)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read row data.
|
||||
*
|
||||
* @param index current data index in row
|
||||
* @param column associate metadata
|
||||
* @param opts query options
|
||||
* @param connOpts connection options
|
||||
* @param packet row packet
|
||||
* @returns {*} data
|
||||
*/
|
||||
readRowData(index, column, opts, connOpts, packet) {
|
||||
switch (column.columnType) {
|
||||
case FieldType.TINY:
|
||||
case FieldType.SHORT:
|
||||
case FieldType.LONG:
|
||||
case FieldType.INT24:
|
||||
case FieldType.YEAR:
|
||||
return packet.readIntLengthEncoded();
|
||||
case FieldType.FLOAT:
|
||||
case FieldType.DOUBLE:
|
||||
return packet.readFloatLengthCoded();
|
||||
case FieldType.LONGLONG:
|
||||
return packet.readLongLengthEncoded(
|
||||
opts.supportBigInt,
|
||||
opts.supportBigNumbers,
|
||||
opts.bigNumberStrings,
|
||||
(column.flags & FieldDetail.UNSIGNED) > 0
|
||||
);
|
||||
case FieldType.DECIMAL:
|
||||
case FieldType.NEWDECIMAL:
|
||||
return packet.readDecimalLengthEncoded(opts.bigNumberStrings);
|
||||
case FieldType.DATE:
|
||||
if (opts.dateStrings) {
|
||||
return packet.readAsciiStringLengthEncoded();
|
||||
}
|
||||
return packet.readDate();
|
||||
case FieldType.DATETIME:
|
||||
case FieldType.TIMESTAMP:
|
||||
if (opts.dateStrings) {
|
||||
return packet.readAsciiStringLengthEncoded();
|
||||
}
|
||||
return packet.readDateTime(opts);
|
||||
case FieldType.TIME:
|
||||
return packet.readAsciiStringLengthEncoded();
|
||||
case FieldType.GEOMETRY:
|
||||
return packet.readGeometry(column.dataTypeName);
|
||||
case FieldType.JSON:
|
||||
//for mysql only => parse string as JSON object
|
||||
return JSON.parse(packet.readStringLengthEncoded('utf8'));
|
||||
|
||||
default:
|
||||
if (column.dataTypeFormat && column.dataTypeFormat === 'json' && opts.autoJsonMap) {
|
||||
return JSON.parse(packet.readStringLengthEncoded('utf8'));
|
||||
}
|
||||
|
||||
if (column.collation.index === 63) {
|
||||
return packet.readBufferLengthEncoded();
|
||||
}
|
||||
const string = packet.readStringLength();
|
||||
if (column.flags & 2048) {
|
||||
//SET
|
||||
return string == null ? null : string === '' ? [] : string.split(',');
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getDatePartQuote(year, mon, day, hour, min, sec, ms) {
|
||||
//return 'YYYY-MM-DD HH:MM:SS' datetime format
|
||||
//see https://mariadb.com/kb/en/library/datetime/
|
||||
return (
|
||||
"'" +
|
||||
(year > 999 ? year : year > 99 ? '0' + year : year > 9 ? '00' + year : '000' + year) +
|
||||
'-' +
|
||||
(mon < 10 ? '0' : '') +
|
||||
mon +
|
||||
'-' +
|
||||
(day < 10 ? '0' : '') +
|
||||
day +
|
||||
' ' +
|
||||
(hour < 10 ? '0' : '') +
|
||||
hour +
|
||||
':' +
|
||||
(min < 10 ? '0' : '') +
|
||||
min +
|
||||
':' +
|
||||
(sec < 10 ? '0' : '') +
|
||||
sec +
|
||||
'.' +
|
||||
(ms > 99 ? ms : ms > 9 ? '0' + ms : '00' + ms) +
|
||||
"'"
|
||||
);
|
||||
}
|
||||
|
||||
function getLocalDate(date, opts) {
|
||||
const year = date.getFullYear();
|
||||
const mon = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const hour = date.getHours();
|
||||
const min = date.getMinutes();
|
||||
const sec = date.getSeconds();
|
||||
const ms = date.getMilliseconds();
|
||||
return getDatePartQuote(year, mon, day, hour, min, sec, ms);
|
||||
}
|
||||
|
||||
function getUtcDate(date, opts) {
|
||||
const year = date.getUTCFullYear();
|
||||
const mon = date.getUTCMonth() + 1;
|
||||
const day = date.getUTCDate();
|
||||
const hour = date.getUTCHours();
|
||||
const min = date.getUTCMinutes();
|
||||
const sec = date.getUTCSeconds();
|
||||
const ms = date.getUTCMilliseconds();
|
||||
return getDatePartQuote(year, mon, day, hour, min, sec, ms);
|
||||
}
|
||||
|
||||
function getTimezoneDate(date, opts) {
|
||||
if (date.getMilliseconds() != 0) {
|
||||
return moment.tz(date, opts.tz).format("'YYYY-MM-DD HH:mm:ss.SSS'");
|
||||
}
|
||||
return moment.tz(date, opts.tz).format("'YYYY-MM-DD HH:mm:ss'");
|
||||
}
|
||||
|
||||
module.exports = CommonText;
|
||||
module.exports.getTimezoneDate = getTimezoneDate;
|
||||
module.exports.getUtcDate = getUtcDate;
|
||||
module.exports.getLocalDate = getLocalDate;
|
||||
167
node_modules/mariadb/lib/cmd/handshake/auth/caching-sha2-password-auth.js
generated
vendored
Normal file
167
node_modules/mariadb/lib/cmd/handshake/auth/caching-sha2-password-auth.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
const PluginAuth = require('./plugin-auth');
|
||||
const fs = require('fs');
|
||||
const crypto = require('crypto');
|
||||
const Errors = require('../../../misc/errors');
|
||||
const NativePasswordAuth = require('./native-password-auth');
|
||||
const Sha256PasswordAuth = require('./sha256-password-auth');
|
||||
|
||||
const State = {
|
||||
INIT: 'INIT',
|
||||
FAST_AUTH_RESULT: 'FAST_AUTH_RESULT',
|
||||
REQUEST_SERVER_KEY: 'REQUEST_SERVER_KEY',
|
||||
SEND_AUTH: 'SEND_AUTH'
|
||||
};
|
||||
|
||||
/**
|
||||
* Use caching Sha2 password authentication
|
||||
*/
|
||||
class CachingSha2PasswordAuth extends PluginAuth {
|
||||
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
|
||||
super(resolve, reject, multiAuthResolver);
|
||||
this.pluginData = pluginData;
|
||||
this.sequenceNo = packSeq;
|
||||
this.counter = 0;
|
||||
this.state = State.INIT;
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
this.exchange(this.pluginData, out, opts, info);
|
||||
this.onPacketReceive = this.response;
|
||||
}
|
||||
|
||||
exchange(buffer, out, opts, info) {
|
||||
switch (this.state) {
|
||||
case State.INIT:
|
||||
const truncatedSeed = this.pluginData.slice(0, this.pluginData.length - 1);
|
||||
const encPwd = NativePasswordAuth.encryptPassword(opts.password, truncatedSeed, 'sha256');
|
||||
out.startPacket(this);
|
||||
if (encPwd.length > 0) {
|
||||
out.writeBuffer(encPwd, 0, encPwd.length);
|
||||
out.flushBuffer(true);
|
||||
} else {
|
||||
out.writeEmptyPacket(true);
|
||||
}
|
||||
this.state = State.FAST_AUTH_RESULT;
|
||||
return;
|
||||
|
||||
case State.FAST_AUTH_RESULT:
|
||||
// length encoded numeric : 0x01 0x03/0x04
|
||||
const fastAuthResult = buffer[1];
|
||||
switch (fastAuthResult) {
|
||||
case 0x03:
|
||||
// success authentication
|
||||
this.emit('send_end');
|
||||
return this.successSend(packet, out, opts, info);
|
||||
|
||||
case 0x04:
|
||||
if (opts.ssl) {
|
||||
// using SSL, so sending password in clear
|
||||
out.startPacket(this);
|
||||
out.writeString(opts.password);
|
||||
out.writeInt8(0);
|
||||
out.flushBuffer(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve public key from configuration or from server
|
||||
if (opts.cachingRsaPublicKey) {
|
||||
try {
|
||||
let key = opts.cachingRsaPublicKey;
|
||||
if (!key.includes('-----BEGIN')) {
|
||||
// rsaPublicKey contain path
|
||||
key = fs.readFileSync(key, 'utf8');
|
||||
}
|
||||
this.publicKey = Sha256PasswordAuth.retreivePublicKey(key);
|
||||
} catch (err) {
|
||||
return this.throwError(err, info);
|
||||
}
|
||||
// send Sha256Password Packet
|
||||
Sha256PasswordAuth.sendSha256PwdPacket(
|
||||
this,
|
||||
this.pluginData,
|
||||
this.publicKey,
|
||||
opts.password,
|
||||
out
|
||||
);
|
||||
} else {
|
||||
if (!opts.allowPublicKeyRetrieval) {
|
||||
return this.throwError(
|
||||
Errors.createError(
|
||||
'RSA public key is not available client side. Either set option `cachingRsaPublicKey` to indicate' +
|
||||
' public key path, or allow public key retrieval with option `allowPublicKeyRetrieval`',
|
||||
true,
|
||||
info,
|
||||
'08S01',
|
||||
Errors.ER_CANNOT_RETRIEVE_RSA_KEY
|
||||
),
|
||||
info
|
||||
);
|
||||
}
|
||||
this.state = State.REQUEST_SERVER_KEY;
|
||||
// ask caching public Key Retrieval
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x02);
|
||||
out.flushBuffer(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case State.REQUEST_SERVER_KEY:
|
||||
this.publicKey = Sha256PasswordAuth.retreivePublicKey(buffer.toString('utf8', 1));
|
||||
this.state = State.SEND_AUTH;
|
||||
Sha256PasswordAuth.sendSha256PwdPacket(
|
||||
this,
|
||||
this.pluginData,
|
||||
this.publicKey,
|
||||
opts.password,
|
||||
out
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static retreivePublicKey(key) {
|
||||
return key.replace('(-+BEGIN PUBLIC KEY-+\\r?\\n|\\n?-+END PUBLIC KEY-+\\r?\\n?)', '');
|
||||
}
|
||||
|
||||
static sendSha256PwdPacket(cmd, pluginData, publicKey, password, out) {
|
||||
const truncatedSeed = pluginData.slice(0, pluginData.length - 1);
|
||||
out.startPacket(cmd);
|
||||
const enc = Sha256PasswordAuth.encrypt(truncatedSeed, password, publicKey);
|
||||
out.writeBuffer(enc, 0, enc.length);
|
||||
out.flushBuffer(cmd);
|
||||
}
|
||||
|
||||
// encrypt password with public key
|
||||
static encrypt(seed, password, publicKey) {
|
||||
const nullFinishedPwd = Buffer.from(password + '\0');
|
||||
const xorBytes = Buffer.allocUnsafe(nullFinishedPwd.length);
|
||||
const seedLength = seed.length;
|
||||
for (let i = 0; i < xorBytes.length; i++) {
|
||||
xorBytes[i] = nullFinishedPwd[i] ^ seed[i % seedLength];
|
||||
}
|
||||
return crypto.publicEncrypt(
|
||||
{ key: publicKey, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING },
|
||||
xorBytes
|
||||
);
|
||||
}
|
||||
|
||||
response(packet, out, opts, info) {
|
||||
const marker = packet.peek();
|
||||
switch (marker) {
|
||||
//*********************************************************************************************************
|
||||
//* OK_Packet and Err_Packet ending packet
|
||||
//*********************************************************************************************************
|
||||
case 0x00:
|
||||
case 0xff:
|
||||
this.emit('send_end');
|
||||
return this.successSend(packet, out, opts, info);
|
||||
|
||||
default:
|
||||
let promptData = packet.readBufferRemaining();
|
||||
this.exchange(promptData, out, opts, info);
|
||||
this.onPacketReceive = this.response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CachingSha2PasswordAuth;
|
||||
23
node_modules/mariadb/lib/cmd/handshake/auth/clear-password-auth.js
generated
vendored
Normal file
23
node_modules/mariadb/lib/cmd/handshake/auth/clear-password-auth.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
const PluginAuth = require('./plugin-auth');
|
||||
|
||||
/**
|
||||
* Send password in clear.
|
||||
* (used only when SSL is active)
|
||||
*/
|
||||
class ClearPasswordAuth extends PluginAuth {
|
||||
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
|
||||
super(resolve, reject, multiAuthResolver);
|
||||
this.sequenceNo = packSeq;
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
out.startPacket(this);
|
||||
if (opts.password) out.writeString(opts.password);
|
||||
out.writeInt8(0);
|
||||
out.flushBuffer(true);
|
||||
this.emit('send_end');
|
||||
this.onPacketReceive = this.successSend;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClearPasswordAuth;
|
||||
833
node_modules/mariadb/lib/cmd/handshake/auth/ed25519-password-auth.js
generated
vendored
Normal file
833
node_modules/mariadb/lib/cmd/handshake/auth/ed25519-password-auth.js
generated
vendored
Normal file
@@ -0,0 +1,833 @@
|
||||
'use strict';
|
||||
|
||||
const PluginAuth = require('./plugin-auth');
|
||||
const Crypto = require('crypto');
|
||||
|
||||
/**
|
||||
* Standard authentication plugin
|
||||
*/
|
||||
class Ed25519PasswordAuth extends PluginAuth {
|
||||
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
|
||||
super(resolve, reject, multiAuthResolver);
|
||||
this.pluginData = pluginData;
|
||||
this.sequenceNo = packSeq;
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
//seed is ended with a null byte value.
|
||||
const data = this.pluginData;
|
||||
|
||||
const sign = Ed25519PasswordAuth.encryptPassword(opts.password, data);
|
||||
out.startPacket(this);
|
||||
out.writeBuffer(sign, 0, sign.length);
|
||||
out.flushBuffer(true);
|
||||
this.emit('send_end');
|
||||
this.onPacketReceive = this.successSend;
|
||||
}
|
||||
|
||||
static encryptPassword(password, seed) {
|
||||
if (!password) return Buffer.alloc(0);
|
||||
|
||||
let i, j;
|
||||
let p = [gf(), gf(), gf(), gf()];
|
||||
const signedMsg = Buffer.alloc(96);
|
||||
const bytePwd = Buffer.from(password);
|
||||
|
||||
let hash = Crypto.createHash('sha512');
|
||||
const d = hash.update(bytePwd).digest();
|
||||
d[0] &= 248;
|
||||
d[31] &= 127;
|
||||
d[31] |= 64;
|
||||
|
||||
for (i = 0; i < 32; i++) signedMsg[64 + i] = seed[i];
|
||||
for (i = 0; i < 32; i++) signedMsg[32 + i] = d[32 + i];
|
||||
|
||||
hash = Crypto.createHash('sha512');
|
||||
const r = hash.update(signedMsg.slice(32, 96)).digest();
|
||||
|
||||
reduce(r);
|
||||
scalarbase(p, r);
|
||||
pack(signedMsg, p);
|
||||
|
||||
p = [gf(), gf(), gf(), gf()];
|
||||
|
||||
scalarbase(p, d);
|
||||
const tt = Buffer.alloc(32);
|
||||
pack(tt, p);
|
||||
|
||||
for (i = 32; i < 64; i++) signedMsg[i] = tt[i - 32];
|
||||
|
||||
hash = Crypto.createHash('sha512');
|
||||
const h = hash.update(signedMsg).digest();
|
||||
|
||||
reduce(h);
|
||||
|
||||
const x = new Float64Array(64);
|
||||
for (i = 0; i < 64; i++) x[i] = 0;
|
||||
for (i = 0; i < 32; i++) x[i] = r[i];
|
||||
for (i = 0; i < 32; i++) {
|
||||
for (j = 0; j < 32; j++) {
|
||||
x[i + j] += h[i] * d[j];
|
||||
}
|
||||
}
|
||||
|
||||
modL(signedMsg.subarray(32), x);
|
||||
|
||||
return signedMsg.slice(0, 64);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************
|
||||
*
|
||||
* This plugin uses the following public domain tweetnacl-js code by Dmitry Chestnykh (from https://github.com/dchest/tweetnacl-js/blob/master/nacl-fast.js).
|
||||
* tweetnacl cannot be used directly (secret key mandatory size is 32 in nacl + implementation differ : second scalarbase use hash of secret key, not secret key).
|
||||
*
|
||||
*******************************************************/
|
||||
|
||||
const gf = function (init) {
|
||||
const r = new Float64Array(16);
|
||||
if (init) for (let i = 0; i < init.length; i++) r[i] = init[i];
|
||||
return r;
|
||||
};
|
||||
|
||||
const gf0 = gf(),
|
||||
gf1 = gf([1]),
|
||||
D2 = gf([
|
||||
0xf159,
|
||||
0x26b2,
|
||||
0x9b94,
|
||||
0xebd6,
|
||||
0xb156,
|
||||
0x8283,
|
||||
0x149a,
|
||||
0x00e0,
|
||||
0xd130,
|
||||
0xeef3,
|
||||
0x80f2,
|
||||
0x198e,
|
||||
0xfce7,
|
||||
0x56df,
|
||||
0xd9dc,
|
||||
0x2406
|
||||
]),
|
||||
X = gf([
|
||||
0xd51a,
|
||||
0x8f25,
|
||||
0x2d60,
|
||||
0xc956,
|
||||
0xa7b2,
|
||||
0x9525,
|
||||
0xc760,
|
||||
0x692c,
|
||||
0xdc5c,
|
||||
0xfdd6,
|
||||
0xe231,
|
||||
0xc0a4,
|
||||
0x53fe,
|
||||
0xcd6e,
|
||||
0x36d3,
|
||||
0x2169
|
||||
]),
|
||||
Y = gf([
|
||||
0x6658,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666,
|
||||
0x6666
|
||||
]);
|
||||
|
||||
const L = new Float64Array([
|
||||
0xed,
|
||||
0xd3,
|
||||
0xf5,
|
||||
0x5c,
|
||||
0x1a,
|
||||
0x63,
|
||||
0x12,
|
||||
0x58,
|
||||
0xd6,
|
||||
0x9c,
|
||||
0xf7,
|
||||
0xa2,
|
||||
0xde,
|
||||
0xf9,
|
||||
0xde,
|
||||
0x14,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0x10
|
||||
]);
|
||||
|
||||
function reduce(r) {
|
||||
const x = new Float64Array(64);
|
||||
let i;
|
||||
for (i = 0; i < 64; i++) x[i] = r[i];
|
||||
for (i = 0; i < 64; i++) r[i] = 0;
|
||||
modL(r, x);
|
||||
}
|
||||
|
||||
function modL(r, x) {
|
||||
let carry, i, j, k;
|
||||
for (i = 63; i >= 32; --i) {
|
||||
carry = 0;
|
||||
for (j = i - 32, k = i - 12; j < k; ++j) {
|
||||
x[j] += carry - 16 * x[i] * L[j - (i - 32)];
|
||||
carry = (x[j] + 128) >> 8;
|
||||
x[j] -= carry * 256;
|
||||
}
|
||||
x[j] += carry;
|
||||
x[i] = 0;
|
||||
}
|
||||
carry = 0;
|
||||
for (j = 0; j < 32; j++) {
|
||||
x[j] += carry - (x[31] >> 4) * L[j];
|
||||
carry = x[j] >> 8;
|
||||
x[j] &= 255;
|
||||
}
|
||||
for (j = 0; j < 32; j++) x[j] -= carry * L[j];
|
||||
for (i = 0; i < 32; i++) {
|
||||
x[i + 1] += x[i] >> 8;
|
||||
r[i] = x[i] & 255;
|
||||
}
|
||||
}
|
||||
|
||||
function scalarbase(p, s) {
|
||||
const q = [gf(), gf(), gf(), gf()];
|
||||
set25519(q[0], X);
|
||||
set25519(q[1], Y);
|
||||
set25519(q[2], gf1);
|
||||
M(q[3], X, Y);
|
||||
scalarmult(p, q, s);
|
||||
}
|
||||
|
||||
function set25519(r, a) {
|
||||
for (let i = 0; i < 16; i++) r[i] = a[i] | 0;
|
||||
}
|
||||
|
||||
function M(o, a, b) {
|
||||
let v,
|
||||
c,
|
||||
t0 = 0,
|
||||
t1 = 0,
|
||||
t2 = 0,
|
||||
t3 = 0,
|
||||
t4 = 0,
|
||||
t5 = 0,
|
||||
t6 = 0,
|
||||
t7 = 0,
|
||||
t8 = 0,
|
||||
t9 = 0,
|
||||
t10 = 0,
|
||||
t11 = 0,
|
||||
t12 = 0,
|
||||
t13 = 0,
|
||||
t14 = 0,
|
||||
t15 = 0,
|
||||
t16 = 0,
|
||||
t17 = 0,
|
||||
t18 = 0,
|
||||
t19 = 0,
|
||||
t20 = 0,
|
||||
t21 = 0,
|
||||
t22 = 0,
|
||||
t23 = 0,
|
||||
t24 = 0,
|
||||
t25 = 0,
|
||||
t26 = 0,
|
||||
t27 = 0,
|
||||
t28 = 0,
|
||||
t29 = 0,
|
||||
t30 = 0;
|
||||
const b0 = b[0],
|
||||
b1 = b[1],
|
||||
b2 = b[2],
|
||||
b3 = b[3],
|
||||
b4 = b[4],
|
||||
b5 = b[5],
|
||||
b6 = b[6],
|
||||
b7 = b[7],
|
||||
b8 = b[8],
|
||||
b9 = b[9],
|
||||
b10 = b[10],
|
||||
b11 = b[11],
|
||||
b12 = b[12],
|
||||
b13 = b[13],
|
||||
b14 = b[14],
|
||||
b15 = b[15];
|
||||
|
||||
v = a[0];
|
||||
t0 += v * b0;
|
||||
t1 += v * b1;
|
||||
t2 += v * b2;
|
||||
t3 += v * b3;
|
||||
t4 += v * b4;
|
||||
t5 += v * b5;
|
||||
t6 += v * b6;
|
||||
t7 += v * b7;
|
||||
t8 += v * b8;
|
||||
t9 += v * b9;
|
||||
t10 += v * b10;
|
||||
t11 += v * b11;
|
||||
t12 += v * b12;
|
||||
t13 += v * b13;
|
||||
t14 += v * b14;
|
||||
t15 += v * b15;
|
||||
v = a[1];
|
||||
t1 += v * b0;
|
||||
t2 += v * b1;
|
||||
t3 += v * b2;
|
||||
t4 += v * b3;
|
||||
t5 += v * b4;
|
||||
t6 += v * b5;
|
||||
t7 += v * b6;
|
||||
t8 += v * b7;
|
||||
t9 += v * b8;
|
||||
t10 += v * b9;
|
||||
t11 += v * b10;
|
||||
t12 += v * b11;
|
||||
t13 += v * b12;
|
||||
t14 += v * b13;
|
||||
t15 += v * b14;
|
||||
t16 += v * b15;
|
||||
v = a[2];
|
||||
t2 += v * b0;
|
||||
t3 += v * b1;
|
||||
t4 += v * b2;
|
||||
t5 += v * b3;
|
||||
t6 += v * b4;
|
||||
t7 += v * b5;
|
||||
t8 += v * b6;
|
||||
t9 += v * b7;
|
||||
t10 += v * b8;
|
||||
t11 += v * b9;
|
||||
t12 += v * b10;
|
||||
t13 += v * b11;
|
||||
t14 += v * b12;
|
||||
t15 += v * b13;
|
||||
t16 += v * b14;
|
||||
t17 += v * b15;
|
||||
v = a[3];
|
||||
t3 += v * b0;
|
||||
t4 += v * b1;
|
||||
t5 += v * b2;
|
||||
t6 += v * b3;
|
||||
t7 += v * b4;
|
||||
t8 += v * b5;
|
||||
t9 += v * b6;
|
||||
t10 += v * b7;
|
||||
t11 += v * b8;
|
||||
t12 += v * b9;
|
||||
t13 += v * b10;
|
||||
t14 += v * b11;
|
||||
t15 += v * b12;
|
||||
t16 += v * b13;
|
||||
t17 += v * b14;
|
||||
t18 += v * b15;
|
||||
v = a[4];
|
||||
t4 += v * b0;
|
||||
t5 += v * b1;
|
||||
t6 += v * b2;
|
||||
t7 += v * b3;
|
||||
t8 += v * b4;
|
||||
t9 += v * b5;
|
||||
t10 += v * b6;
|
||||
t11 += v * b7;
|
||||
t12 += v * b8;
|
||||
t13 += v * b9;
|
||||
t14 += v * b10;
|
||||
t15 += v * b11;
|
||||
t16 += v * b12;
|
||||
t17 += v * b13;
|
||||
t18 += v * b14;
|
||||
t19 += v * b15;
|
||||
v = a[5];
|
||||
t5 += v * b0;
|
||||
t6 += v * b1;
|
||||
t7 += v * b2;
|
||||
t8 += v * b3;
|
||||
t9 += v * b4;
|
||||
t10 += v * b5;
|
||||
t11 += v * b6;
|
||||
t12 += v * b7;
|
||||
t13 += v * b8;
|
||||
t14 += v * b9;
|
||||
t15 += v * b10;
|
||||
t16 += v * b11;
|
||||
t17 += v * b12;
|
||||
t18 += v * b13;
|
||||
t19 += v * b14;
|
||||
t20 += v * b15;
|
||||
v = a[6];
|
||||
t6 += v * b0;
|
||||
t7 += v * b1;
|
||||
t8 += v * b2;
|
||||
t9 += v * b3;
|
||||
t10 += v * b4;
|
||||
t11 += v * b5;
|
||||
t12 += v * b6;
|
||||
t13 += v * b7;
|
||||
t14 += v * b8;
|
||||
t15 += v * b9;
|
||||
t16 += v * b10;
|
||||
t17 += v * b11;
|
||||
t18 += v * b12;
|
||||
t19 += v * b13;
|
||||
t20 += v * b14;
|
||||
t21 += v * b15;
|
||||
v = a[7];
|
||||
t7 += v * b0;
|
||||
t8 += v * b1;
|
||||
t9 += v * b2;
|
||||
t10 += v * b3;
|
||||
t11 += v * b4;
|
||||
t12 += v * b5;
|
||||
t13 += v * b6;
|
||||
t14 += v * b7;
|
||||
t15 += v * b8;
|
||||
t16 += v * b9;
|
||||
t17 += v * b10;
|
||||
t18 += v * b11;
|
||||
t19 += v * b12;
|
||||
t20 += v * b13;
|
||||
t21 += v * b14;
|
||||
t22 += v * b15;
|
||||
v = a[8];
|
||||
t8 += v * b0;
|
||||
t9 += v * b1;
|
||||
t10 += v * b2;
|
||||
t11 += v * b3;
|
||||
t12 += v * b4;
|
||||
t13 += v * b5;
|
||||
t14 += v * b6;
|
||||
t15 += v * b7;
|
||||
t16 += v * b8;
|
||||
t17 += v * b9;
|
||||
t18 += v * b10;
|
||||
t19 += v * b11;
|
||||
t20 += v * b12;
|
||||
t21 += v * b13;
|
||||
t22 += v * b14;
|
||||
t23 += v * b15;
|
||||
v = a[9];
|
||||
t9 += v * b0;
|
||||
t10 += v * b1;
|
||||
t11 += v * b2;
|
||||
t12 += v * b3;
|
||||
t13 += v * b4;
|
||||
t14 += v * b5;
|
||||
t15 += v * b6;
|
||||
t16 += v * b7;
|
||||
t17 += v * b8;
|
||||
t18 += v * b9;
|
||||
t19 += v * b10;
|
||||
t20 += v * b11;
|
||||
t21 += v * b12;
|
||||
t22 += v * b13;
|
||||
t23 += v * b14;
|
||||
t24 += v * b15;
|
||||
v = a[10];
|
||||
t10 += v * b0;
|
||||
t11 += v * b1;
|
||||
t12 += v * b2;
|
||||
t13 += v * b3;
|
||||
t14 += v * b4;
|
||||
t15 += v * b5;
|
||||
t16 += v * b6;
|
||||
t17 += v * b7;
|
||||
t18 += v * b8;
|
||||
t19 += v * b9;
|
||||
t20 += v * b10;
|
||||
t21 += v * b11;
|
||||
t22 += v * b12;
|
||||
t23 += v * b13;
|
||||
t24 += v * b14;
|
||||
t25 += v * b15;
|
||||
v = a[11];
|
||||
t11 += v * b0;
|
||||
t12 += v * b1;
|
||||
t13 += v * b2;
|
||||
t14 += v * b3;
|
||||
t15 += v * b4;
|
||||
t16 += v * b5;
|
||||
t17 += v * b6;
|
||||
t18 += v * b7;
|
||||
t19 += v * b8;
|
||||
t20 += v * b9;
|
||||
t21 += v * b10;
|
||||
t22 += v * b11;
|
||||
t23 += v * b12;
|
||||
t24 += v * b13;
|
||||
t25 += v * b14;
|
||||
t26 += v * b15;
|
||||
v = a[12];
|
||||
t12 += v * b0;
|
||||
t13 += v * b1;
|
||||
t14 += v * b2;
|
||||
t15 += v * b3;
|
||||
t16 += v * b4;
|
||||
t17 += v * b5;
|
||||
t18 += v * b6;
|
||||
t19 += v * b7;
|
||||
t20 += v * b8;
|
||||
t21 += v * b9;
|
||||
t22 += v * b10;
|
||||
t23 += v * b11;
|
||||
t24 += v * b12;
|
||||
t25 += v * b13;
|
||||
t26 += v * b14;
|
||||
t27 += v * b15;
|
||||
v = a[13];
|
||||
t13 += v * b0;
|
||||
t14 += v * b1;
|
||||
t15 += v * b2;
|
||||
t16 += v * b3;
|
||||
t17 += v * b4;
|
||||
t18 += v * b5;
|
||||
t19 += v * b6;
|
||||
t20 += v * b7;
|
||||
t21 += v * b8;
|
||||
t22 += v * b9;
|
||||
t23 += v * b10;
|
||||
t24 += v * b11;
|
||||
t25 += v * b12;
|
||||
t26 += v * b13;
|
||||
t27 += v * b14;
|
||||
t28 += v * b15;
|
||||
v = a[14];
|
||||
t14 += v * b0;
|
||||
t15 += v * b1;
|
||||
t16 += v * b2;
|
||||
t17 += v * b3;
|
||||
t18 += v * b4;
|
||||
t19 += v * b5;
|
||||
t20 += v * b6;
|
||||
t21 += v * b7;
|
||||
t22 += v * b8;
|
||||
t23 += v * b9;
|
||||
t24 += v * b10;
|
||||
t25 += v * b11;
|
||||
t26 += v * b12;
|
||||
t27 += v * b13;
|
||||
t28 += v * b14;
|
||||
t29 += v * b15;
|
||||
v = a[15];
|
||||
t15 += v * b0;
|
||||
t16 += v * b1;
|
||||
t17 += v * b2;
|
||||
t18 += v * b3;
|
||||
t19 += v * b4;
|
||||
t20 += v * b5;
|
||||
t21 += v * b6;
|
||||
t22 += v * b7;
|
||||
t23 += v * b8;
|
||||
t24 += v * b9;
|
||||
t25 += v * b10;
|
||||
t26 += v * b11;
|
||||
t27 += v * b12;
|
||||
t28 += v * b13;
|
||||
t29 += v * b14;
|
||||
t30 += v * b15;
|
||||
|
||||
t0 += 38 * t16;
|
||||
t1 += 38 * t17;
|
||||
t2 += 38 * t18;
|
||||
t3 += 38 * t19;
|
||||
t4 += 38 * t20;
|
||||
t5 += 38 * t21;
|
||||
t6 += 38 * t22;
|
||||
t7 += 38 * t23;
|
||||
t8 += 38 * t24;
|
||||
t9 += 38 * t25;
|
||||
t10 += 38 * t26;
|
||||
t11 += 38 * t27;
|
||||
t12 += 38 * t28;
|
||||
t13 += 38 * t29;
|
||||
t14 += 38 * t30;
|
||||
// t15 left as is
|
||||
|
||||
// first car
|
||||
c = 1;
|
||||
v = t0 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t0 = v - c * 65536;
|
||||
v = t1 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t1 = v - c * 65536;
|
||||
v = t2 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t2 = v - c * 65536;
|
||||
v = t3 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t3 = v - c * 65536;
|
||||
v = t4 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t4 = v - c * 65536;
|
||||
v = t5 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t5 = v - c * 65536;
|
||||
v = t6 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t6 = v - c * 65536;
|
||||
v = t7 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t7 = v - c * 65536;
|
||||
v = t8 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t8 = v - c * 65536;
|
||||
v = t9 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t9 = v - c * 65536;
|
||||
v = t10 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t10 = v - c * 65536;
|
||||
v = t11 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t11 = v - c * 65536;
|
||||
v = t12 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t12 = v - c * 65536;
|
||||
v = t13 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t13 = v - c * 65536;
|
||||
v = t14 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t14 = v - c * 65536;
|
||||
v = t15 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t15 = v - c * 65536;
|
||||
t0 += c - 1 + 37 * (c - 1);
|
||||
|
||||
// second car
|
||||
c = 1;
|
||||
v = t0 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t0 = v - c * 65536;
|
||||
v = t1 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t1 = v - c * 65536;
|
||||
v = t2 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t2 = v - c * 65536;
|
||||
v = t3 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t3 = v - c * 65536;
|
||||
v = t4 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t4 = v - c * 65536;
|
||||
v = t5 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t5 = v - c * 65536;
|
||||
v = t6 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t6 = v - c * 65536;
|
||||
v = t7 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t7 = v - c * 65536;
|
||||
v = t8 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t8 = v - c * 65536;
|
||||
v = t9 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t9 = v - c * 65536;
|
||||
v = t10 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t10 = v - c * 65536;
|
||||
v = t11 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t11 = v - c * 65536;
|
||||
v = t12 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t12 = v - c * 65536;
|
||||
v = t13 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t13 = v - c * 65536;
|
||||
v = t14 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t14 = v - c * 65536;
|
||||
v = t15 + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
t15 = v - c * 65536;
|
||||
t0 += c - 1 + 37 * (c - 1);
|
||||
|
||||
o[0] = t0;
|
||||
o[1] = t1;
|
||||
o[2] = t2;
|
||||
o[3] = t3;
|
||||
o[4] = t4;
|
||||
o[5] = t5;
|
||||
o[6] = t6;
|
||||
o[7] = t7;
|
||||
o[8] = t8;
|
||||
o[9] = t9;
|
||||
o[10] = t10;
|
||||
o[11] = t11;
|
||||
o[12] = t12;
|
||||
o[13] = t13;
|
||||
o[14] = t14;
|
||||
o[15] = t15;
|
||||
}
|
||||
|
||||
function scalarmult(p, q, s) {
|
||||
let b, i;
|
||||
set25519(p[0], gf0);
|
||||
set25519(p[1], gf1);
|
||||
set25519(p[2], gf1);
|
||||
set25519(p[3], gf0);
|
||||
for (i = 255; i >= 0; --i) {
|
||||
b = (s[(i / 8) | 0] >> (i & 7)) & 1;
|
||||
cswap(p, q, b);
|
||||
add(q, p);
|
||||
add(p, p);
|
||||
cswap(p, q, b);
|
||||
}
|
||||
}
|
||||
|
||||
function pack(r, p) {
|
||||
const tx = gf(),
|
||||
ty = gf(),
|
||||
zi = gf();
|
||||
inv25519(zi, p[2]);
|
||||
M(tx, p[0], zi);
|
||||
M(ty, p[1], zi);
|
||||
pack25519(r, ty);
|
||||
r[31] ^= par25519(tx) << 7;
|
||||
}
|
||||
|
||||
function inv25519(o, i) {
|
||||
const c = gf();
|
||||
let a;
|
||||
for (a = 0; a < 16; a++) c[a] = i[a];
|
||||
for (a = 253; a >= 0; a--) {
|
||||
S(c, c);
|
||||
if (a !== 2 && a !== 4) M(c, c, i);
|
||||
}
|
||||
for (a = 0; a < 16; a++) o[a] = c[a];
|
||||
}
|
||||
|
||||
function S(o, a) {
|
||||
M(o, a, a);
|
||||
}
|
||||
|
||||
function par25519(a) {
|
||||
const d = new Uint8Array(32);
|
||||
pack25519(d, a);
|
||||
return d[0] & 1;
|
||||
}
|
||||
function car25519(o) {
|
||||
let i,
|
||||
v,
|
||||
c = 1;
|
||||
for (i = 0; i < 16; i++) {
|
||||
v = o[i] + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
o[i] = v - c * 65536;
|
||||
}
|
||||
o[0] += c - 1 + 37 * (c - 1);
|
||||
}
|
||||
|
||||
function pack25519(o, n) {
|
||||
let i, j, b;
|
||||
const m = gf(),
|
||||
t = gf();
|
||||
for (i = 0; i < 16; i++) t[i] = n[i];
|
||||
car25519(t);
|
||||
car25519(t);
|
||||
car25519(t);
|
||||
for (j = 0; j < 2; j++) {
|
||||
m[0] = t[0] - 0xffed;
|
||||
for (i = 1; i < 15; i++) {
|
||||
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
|
||||
m[i - 1] &= 0xffff;
|
||||
}
|
||||
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
|
||||
b = (m[15] >> 16) & 1;
|
||||
m[14] &= 0xffff;
|
||||
sel25519(t, m, 1 - b);
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
o[2 * i] = t[i] & 0xff;
|
||||
o[2 * i + 1] = t[i] >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
function cswap(p, q, b) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
sel25519(p[i], q[i], b);
|
||||
}
|
||||
}
|
||||
|
||||
function A(o, a, b) {
|
||||
for (let i = 0; i < 16; i++) o[i] = a[i] + b[i];
|
||||
}
|
||||
|
||||
function Z(o, a, b) {
|
||||
for (let i = 0; i < 16; i++) o[i] = a[i] - b[i];
|
||||
}
|
||||
|
||||
function add(p, q) {
|
||||
const a = gf(),
|
||||
b = gf(),
|
||||
c = gf(),
|
||||
d = gf(),
|
||||
e = gf(),
|
||||
f = gf(),
|
||||
g = gf(),
|
||||
h = gf(),
|
||||
t = gf();
|
||||
|
||||
Z(a, p[1], p[0]);
|
||||
Z(t, q[1], q[0]);
|
||||
M(a, a, t);
|
||||
A(b, p[0], p[1]);
|
||||
A(t, q[0], q[1]);
|
||||
M(b, b, t);
|
||||
M(c, p[3], q[3]);
|
||||
M(c, c, D2);
|
||||
M(d, p[2], q[2]);
|
||||
A(d, d, d);
|
||||
Z(e, b, a);
|
||||
Z(f, d, c);
|
||||
A(g, d, c);
|
||||
A(h, b, a);
|
||||
|
||||
M(p[0], e, f);
|
||||
M(p[1], h, g);
|
||||
M(p[2], g, f);
|
||||
M(p[3], e, h);
|
||||
}
|
||||
|
||||
function sel25519(p, q, b) {
|
||||
const c = ~(b - 1);
|
||||
let t;
|
||||
for (let i = 0; i < 16; i++) {
|
||||
t = c & (p[i] ^ q[i]);
|
||||
p[i] ^= t;
|
||||
q[i] ^= t;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Ed25519PasswordAuth;
|
||||
55
node_modules/mariadb/lib/cmd/handshake/auth/native-password-auth.js
generated
vendored
Normal file
55
node_modules/mariadb/lib/cmd/handshake/auth/native-password-auth.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
const PluginAuth = require('./plugin-auth');
|
||||
const Crypto = require('crypto');
|
||||
|
||||
/**
|
||||
* Standard authentication plugin
|
||||
*/
|
||||
class NativePasswordAuth extends PluginAuth {
|
||||
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
|
||||
super(resolve, reject, multiAuthResolver);
|
||||
this.pluginData = pluginData;
|
||||
this.sequenceNo = packSeq;
|
||||
this.compressSequenceNo = compressPackSeq;
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
//seed is ended with a null byte value.
|
||||
const data = this.pluginData.slice(0, 20);
|
||||
let authToken = NativePasswordAuth.encryptPassword(opts.password, data, 'sha1');
|
||||
|
||||
out.startPacket(this);
|
||||
if (authToken.length > 0) {
|
||||
out.writeBuffer(authToken, 0, authToken.length);
|
||||
out.flushBuffer(true);
|
||||
} else {
|
||||
out.writeEmptyPacket(true);
|
||||
}
|
||||
this.emit('send_end');
|
||||
this.onPacketReceive = this.successSend;
|
||||
}
|
||||
|
||||
static encryptPassword(password, seed, algorithm) {
|
||||
if (!password) return Buffer.alloc(0);
|
||||
|
||||
let hash = Crypto.createHash(algorithm);
|
||||
let stage1 = hash.update(password, 'utf8').digest();
|
||||
hash = Crypto.createHash(algorithm);
|
||||
|
||||
let stage2 = hash.update(stage1).digest();
|
||||
hash = Crypto.createHash(algorithm);
|
||||
|
||||
hash.update(seed);
|
||||
hash.update(stage2);
|
||||
|
||||
let digest = hash.digest();
|
||||
let returnBytes = Buffer.allocUnsafe(digest.length);
|
||||
for (let i = 0; i < digest.length; i++) {
|
||||
returnBytes[i] = stage1[i] ^ digest[i];
|
||||
}
|
||||
return returnBytes;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NativePasswordAuth;
|
||||
58
node_modules/mariadb/lib/cmd/handshake/auth/pam-password-auth.js
generated
vendored
Normal file
58
node_modules/mariadb/lib/cmd/handshake/auth/pam-password-auth.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
const PluginAuth = require('./plugin-auth');
|
||||
|
||||
/**
|
||||
* Use PAM authentication
|
||||
*/
|
||||
class PamPasswordAuth extends PluginAuth {
|
||||
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
|
||||
super(resolve, reject, multiAuthResolver);
|
||||
this.pluginData = pluginData;
|
||||
this.sequenceNo = packSeq;
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
this.exchange(this.pluginData, out, opts, info);
|
||||
this.onPacketReceive = this.response;
|
||||
}
|
||||
|
||||
exchange(buffer, out, opts, info) {
|
||||
//conversation is :
|
||||
// - first byte is information tell if question is a password (4) or clear text (2).
|
||||
// - other bytes are the question to user
|
||||
|
||||
out.startPacket(this);
|
||||
|
||||
let pwd;
|
||||
if (Array.isArray(opts.password)) {
|
||||
pwd = opts.password[this.counter];
|
||||
this.counter++;
|
||||
} else {
|
||||
pwd = opts.password;
|
||||
}
|
||||
|
||||
if (pwd) out.writeString(pwd);
|
||||
out.writeInt8(0);
|
||||
out.flushBuffer(true);
|
||||
}
|
||||
|
||||
response(packet, out, opts, info) {
|
||||
const marker = packet.peek();
|
||||
switch (marker) {
|
||||
//*********************************************************************************************************
|
||||
//* OK_Packet and Err_Packet ending packet
|
||||
//*********************************************************************************************************
|
||||
case 0x00:
|
||||
case 0xff:
|
||||
this.emit('send_end');
|
||||
return this.successSend(packet, out, opts, info);
|
||||
|
||||
default:
|
||||
let promptData = packet.readBuffer();
|
||||
this.exchange(promptData, out, opts, info);
|
||||
this.onPacketReceive = this.response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PamPasswordAuth;
|
||||
19
node_modules/mariadb/lib/cmd/handshake/auth/plugin-auth.js
generated
vendored
Normal file
19
node_modules/mariadb/lib/cmd/handshake/auth/plugin-auth.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const Command = require('../../command');
|
||||
|
||||
/**
|
||||
* Base authentication plugin
|
||||
*/
|
||||
class PluginAuth extends Command {
|
||||
constructor(resolve, reject, multiAuthResolver) {
|
||||
super(resolve, reject);
|
||||
this.multiAuthResolver = multiAuthResolver;
|
||||
}
|
||||
|
||||
successSend(packet, out, opts, info) {
|
||||
this.multiAuthResolver(packet, out, opts, info);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PluginAuth;
|
||||
142
node_modules/mariadb/lib/cmd/handshake/auth/sha256-password-auth.js
generated
vendored
Normal file
142
node_modules/mariadb/lib/cmd/handshake/auth/sha256-password-auth.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
const PluginAuth = require('./plugin-auth');
|
||||
const fs = require('fs');
|
||||
const crypto = require('crypto');
|
||||
const Errors = require('../../../misc/errors');
|
||||
|
||||
/**
|
||||
* Use Sha256 authentication
|
||||
*/
|
||||
class Sha256PasswordAuth extends PluginAuth {
|
||||
constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
|
||||
super(resolve, reject, multiAuthResolver);
|
||||
this.pluginData = pluginData;
|
||||
this.sequenceNo = packSeq;
|
||||
this.counter = 0;
|
||||
this.initialState = true;
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
this.exchange(this.pluginData, out, opts, info);
|
||||
this.onPacketReceive = this.response;
|
||||
}
|
||||
|
||||
exchange(buffer, out, opts, info) {
|
||||
if (this.initialState) {
|
||||
if (!opts.password) {
|
||||
out.startPacket(this);
|
||||
out.writeEmptyPacket(true);
|
||||
return;
|
||||
} else if (opts.ssl) {
|
||||
// using SSL, so sending password in clear
|
||||
out.startPacket(this);
|
||||
if (opts.password) {
|
||||
out.writeString(opts.password);
|
||||
}
|
||||
out.writeInt8(0);
|
||||
out.flushBuffer(true);
|
||||
return;
|
||||
} else {
|
||||
// retrieve public key from configuration or from server
|
||||
if (opts.rsaPublicKey) {
|
||||
try {
|
||||
let key = opts.rsaPublicKey;
|
||||
if (!key.includes('-----BEGIN')) {
|
||||
// rsaPublicKey contain path
|
||||
key = fs.readFileSync(key, 'utf8');
|
||||
}
|
||||
this.publicKey = Sha256PasswordAuth.retreivePublicKey(key);
|
||||
} catch (err) {
|
||||
return this.throwError(err, info);
|
||||
}
|
||||
} else {
|
||||
if (!opts.allowPublicKeyRetrieval) {
|
||||
return this.throwError(
|
||||
Errors.createError(
|
||||
'RSA public key is not available client side. Either set option `rsaPublicKey` to indicate' +
|
||||
' public key path, or allow public key retrieval with option `allowPublicKeyRetrieval`',
|
||||
|
||||
true,
|
||||
info,
|
||||
'08S01',
|
||||
Errors.ER_CANNOT_RETRIEVE_RSA_KEY
|
||||
),
|
||||
info
|
||||
);
|
||||
}
|
||||
this.initialState = false;
|
||||
|
||||
// ask public Key Retrieval
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x01);
|
||||
out.flushBuffer(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// send Sha256Password Packet
|
||||
Sha256PasswordAuth.sendSha256PwdPacket(
|
||||
this,
|
||||
this.pluginData,
|
||||
this.publicKey,
|
||||
opts.password,
|
||||
out
|
||||
);
|
||||
} else {
|
||||
// has request public key
|
||||
this.publicKey = Sha256PasswordAuth.retreivePublicKey(buffer.toString('utf8', 1));
|
||||
Sha256PasswordAuth.sendSha256PwdPacket(
|
||||
this,
|
||||
this.pluginData,
|
||||
this.publicKey,
|
||||
opts.password,
|
||||
out
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static retreivePublicKey(key) {
|
||||
return key.replace('(-+BEGIN PUBLIC KEY-+\\r?\\n|\\n?-+END PUBLIC KEY-+\\r?\\n?)', '');
|
||||
}
|
||||
|
||||
static sendSha256PwdPacket(cmd, pluginData, publicKey, password, out) {
|
||||
const truncatedSeed = pluginData.slice(0, pluginData.length - 1);
|
||||
out.startPacket(cmd);
|
||||
const enc = Sha256PasswordAuth.encrypt(truncatedSeed, password, publicKey);
|
||||
out.writeBuffer(enc, 0, enc.length);
|
||||
out.flushBuffer(cmd);
|
||||
}
|
||||
|
||||
// encrypt password with public key
|
||||
static encrypt(seed, password, publicKey) {
|
||||
const nullFinishedPwd = Buffer.from(password + '\0');
|
||||
const xorBytes = Buffer.allocUnsafe(nullFinishedPwd.length);
|
||||
const seedLength = seed.length;
|
||||
for (let i = 0; i < xorBytes.length; i++) {
|
||||
xorBytes[i] = nullFinishedPwd[i] ^ seed[i % seedLength];
|
||||
}
|
||||
return crypto.publicEncrypt(
|
||||
{ key: publicKey, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING },
|
||||
xorBytes
|
||||
);
|
||||
}
|
||||
|
||||
response(packet, out, opts, info) {
|
||||
const marker = packet.peek();
|
||||
switch (marker) {
|
||||
//*********************************************************************************************************
|
||||
//* OK_Packet and Err_Packet ending packet
|
||||
//*********************************************************************************************************
|
||||
case 0x00:
|
||||
case 0xff:
|
||||
this.emit('send_end');
|
||||
return this.successSend(packet, out, opts, info);
|
||||
|
||||
default:
|
||||
let promptData = packet.readBufferRemaining();
|
||||
this.exchange(promptData, out, opts, info);
|
||||
this.onPacketReceive = this.response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Sha256PasswordAuth;
|
||||
74
node_modules/mariadb/lib/cmd/handshake/client-capabilities.js
generated
vendored
Normal file
74
node_modules/mariadb/lib/cmd/handshake/client-capabilities.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
|
||||
const Capabilities = require('../../const/capabilities');
|
||||
|
||||
/**
|
||||
* Initialize client capabilities according to options and server capabilities
|
||||
*
|
||||
* @param opts options
|
||||
* @param info information
|
||||
*/
|
||||
module.exports.init = function (opts, info) {
|
||||
let capabilities =
|
||||
Capabilities.IGNORE_SPACE |
|
||||
Capabilities.PROTOCOL_41 |
|
||||
Capabilities.TRANSACTIONS |
|
||||
Capabilities.SECURE_CONNECTION |
|
||||
Capabilities.MULTI_RESULTS |
|
||||
Capabilities.PS_MULTI_RESULTS |
|
||||
Capabilities.SESSION_TRACK |
|
||||
Capabilities.PLUGIN_AUTH_LENENC_CLIENT_DATA;
|
||||
|
||||
if ((info.serverCapabilities & Capabilities.MYSQL) === BigInt(0)) {
|
||||
capabilities |= Capabilities.MARIADB_CLIENT_EXTENDED_TYPE_INFO;
|
||||
}
|
||||
|
||||
if (info.serverCapabilities & Capabilities.PLUGIN_AUTH) {
|
||||
capabilities |= Capabilities.PLUGIN_AUTH;
|
||||
}
|
||||
|
||||
if (opts.connectAttributes && info.serverCapabilities & Capabilities.CONNECT_ATTRS) {
|
||||
capabilities |= Capabilities.CONNECT_ATTRS;
|
||||
}
|
||||
|
||||
if (opts.foundRows) {
|
||||
capabilities |= Capabilities.FOUND_ROWS;
|
||||
}
|
||||
|
||||
if (opts.permitLocalInfile) {
|
||||
capabilities |= Capabilities.LOCAL_FILES;
|
||||
}
|
||||
|
||||
if (opts.multipleStatements) {
|
||||
capabilities |= Capabilities.MULTI_STATEMENTS;
|
||||
}
|
||||
|
||||
info.eofDeprecated = (info.serverCapabilities & Capabilities.DEPRECATE_EOF) > 0;
|
||||
if (info.eofDeprecated) {
|
||||
capabilities |= Capabilities.DEPRECATE_EOF;
|
||||
}
|
||||
|
||||
if (opts.database && info.serverCapabilities & Capabilities.CONNECT_WITH_DB) {
|
||||
capabilities |= Capabilities.CONNECT_WITH_DB;
|
||||
}
|
||||
|
||||
// use compression only if requested by client and supported by server
|
||||
if (opts.compress) {
|
||||
if (info.serverCapabilities & Capabilities.COMPRESS) {
|
||||
capabilities |= Capabilities.COMPRESS;
|
||||
} else {
|
||||
opts.compress = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.bulk) {
|
||||
if (info.serverCapabilities & Capabilities.MARIADB_CLIENT_STMT_BULK_OPERATIONS) {
|
||||
capabilities |= Capabilities.MARIADB_CLIENT_STMT_BULK_OPERATIONS;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.permitConnectionWhenExpired) {
|
||||
capabilities |= Capabilities.CAN_HANDLE_EXPIRED_PASSWORDS;
|
||||
}
|
||||
info.clientCapabilities = capabilities;
|
||||
};
|
||||
126
node_modules/mariadb/lib/cmd/handshake/client-handshake-response.js
generated
vendored
Normal file
126
node_modules/mariadb/lib/cmd/handshake/client-handshake-response.js
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
'use strict';
|
||||
|
||||
const Capabilities = require('../../const/capabilities');
|
||||
const Iconv = require('iconv-lite');
|
||||
const NativePasswordAuth = require('./auth/native-password-auth');
|
||||
const Ed25519PasswordAuth = require('./auth/ed25519-password-auth');
|
||||
const driverVersion = require('../../../package.json').version;
|
||||
const os = require('os');
|
||||
|
||||
/**
|
||||
* Send Handshake response packet
|
||||
* see https://mariadb.com/kb/en/library/1-connecting-connecting/#handshake-response-packet
|
||||
*
|
||||
* @param cmd current handshake command
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param pluginName plugin name
|
||||
* @param info connection information
|
||||
*/
|
||||
module.exports.send = function send(cmd, out, opts, pluginName, info) {
|
||||
out.startPacket(cmd);
|
||||
info.defaultPluginName = pluginName;
|
||||
const pwd = Array.isArray(opts.password) ? opts.password[0] : opts.password;
|
||||
let authToken;
|
||||
let authPlugin;
|
||||
switch (pluginName) {
|
||||
case 'client_ed25519':
|
||||
authToken = Ed25519PasswordAuth.encryptPassword(pwd, info.seed);
|
||||
authPlugin = 'client_ed25519';
|
||||
break;
|
||||
|
||||
case 'mysql_clear_password':
|
||||
authToken = Buffer.from(pwd);
|
||||
authPlugin = 'mysql_clear_password';
|
||||
break;
|
||||
|
||||
default:
|
||||
authToken = NativePasswordAuth.encryptPassword(pwd, info.seed, 'sha1');
|
||||
authPlugin = 'mysql_native_password';
|
||||
break;
|
||||
}
|
||||
out.writeInt32(Number(info.clientCapabilities & BigInt(0xffffffff)));
|
||||
out.writeInt32(1024 * 1024 * 1024); // max packet size
|
||||
out.writeInt8(opts.collation.index);
|
||||
for (let i = 0; i < 19; i++) {
|
||||
out.writeInt8(0);
|
||||
}
|
||||
|
||||
out.writeInt32(Number(info.clientCapabilities >> BigInt(32)));
|
||||
|
||||
//null encoded user
|
||||
out.writeString(opts.user || '');
|
||||
out.writeInt8(0);
|
||||
|
||||
if (info.serverCapabilities & Capabilities.PLUGIN_AUTH_LENENC_CLIENT_DATA) {
|
||||
out.writeLengthCoded(authToken.length);
|
||||
out.writeBuffer(authToken, 0, authToken.length);
|
||||
} else if (info.serverCapabilities & Capabilities.SECURE_CONNECTION) {
|
||||
out.writeInt8(authToken.length);
|
||||
out.writeBuffer(authToken, 0, authToken.length);
|
||||
} else {
|
||||
out.writeBuffer(authToken, 0, authToken.length);
|
||||
out.writeInt8(0);
|
||||
}
|
||||
|
||||
if (info.clientCapabilities & Capabilities.CONNECT_WITH_DB) {
|
||||
out.writeString(opts.database);
|
||||
out.writeInt8(0);
|
||||
info.database = opts.database;
|
||||
}
|
||||
|
||||
if (info.clientCapabilities & Capabilities.PLUGIN_AUTH) {
|
||||
out.writeString(authPlugin);
|
||||
out.writeInt8(0);
|
||||
}
|
||||
|
||||
if (info.clientCapabilities & Capabilities.CONNECT_ATTRS) {
|
||||
out.writeInt8(0xfc);
|
||||
let initPos = out.pos; //save position, assuming connection attributes length will be less than 2 bytes length
|
||||
out.writeInt16(0);
|
||||
|
||||
const encoding = opts.collation.charset;
|
||||
|
||||
writeParam(out, '_client_name', encoding);
|
||||
writeParam(out, 'MariaDB connector/Node', encoding);
|
||||
|
||||
writeParam(out, '_client_version', encoding);
|
||||
writeParam(out, driverVersion, encoding);
|
||||
|
||||
const address = cmd.getSocket().address().address;
|
||||
if (address) {
|
||||
writeParam(out, '_server_host', encoding);
|
||||
writeParam(out, address, encoding);
|
||||
}
|
||||
|
||||
writeParam(out, '_os', encoding);
|
||||
writeParam(out, process.platform, encoding);
|
||||
|
||||
writeParam(out, '_client_host', encoding);
|
||||
writeParam(out, os.hostname(), encoding);
|
||||
|
||||
writeParam(out, '_node_version', encoding);
|
||||
writeParam(out, process.versions.node, encoding);
|
||||
|
||||
if (opts.connectAttributes !== true) {
|
||||
let attrNames = Object.keys(opts.connectAttributes);
|
||||
for (let k = 0; k < attrNames.length; ++k) {
|
||||
writeParam(out, attrNames[k], encoding);
|
||||
writeParam(out, opts.connectAttributes[attrNames[k]], encoding);
|
||||
}
|
||||
}
|
||||
|
||||
//write end size
|
||||
out.writeInt16AtPos(initPos);
|
||||
}
|
||||
|
||||
out.flushBuffer(true);
|
||||
};
|
||||
|
||||
function writeParam(out, val, encoding) {
|
||||
let param = Buffer.isEncoding(encoding)
|
||||
? Buffer.from(val, encoding)
|
||||
: Iconv.encode(val, encoding);
|
||||
out.writeLengthCoded(param.length);
|
||||
out.writeBuffer(param, 0, param.length);
|
||||
}
|
||||
287
node_modules/mariadb/lib/cmd/handshake/handshake.js
generated
vendored
Normal file
287
node_modules/mariadb/lib/cmd/handshake/handshake.js
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
'use strict';
|
||||
|
||||
const Command = require('../command');
|
||||
const InitialHandshake = require('./initial-handshake');
|
||||
const ClientHandshakeResponse = require('./client-handshake-response');
|
||||
const SslRequest = require('./ssl-request');
|
||||
const ClientCapabilities = require('./client-capabilities');
|
||||
const Errors = require('../../misc/errors');
|
||||
const Capabilities = require('../../const/capabilities');
|
||||
const process = require('process');
|
||||
|
||||
/**
|
||||
* Handle handshake.
|
||||
* see https://mariadb.com/kb/en/library/1-connecting-connecting/
|
||||
*/
|
||||
class Handshake extends Command {
|
||||
constructor(resolve, reject, _createSecureContext, _addCommand, getSocket) {
|
||||
super(resolve, reject);
|
||||
this._createSecureContext = _createSecureContext;
|
||||
this._addCommand = _addCommand;
|
||||
this.getSocket = getSocket;
|
||||
this.onPacketReceive = this.parseHandshakeInit;
|
||||
this.plugin = this;
|
||||
}
|
||||
|
||||
ensureOptionCompatibility(opts, info) {
|
||||
if (
|
||||
opts.multipleStatements &&
|
||||
(info.serverCapabilities & Capabilities.MULTI_STATEMENTS) === 0
|
||||
) {
|
||||
return this.throwNewError(
|
||||
"Option `multipleStatements` enable, but server doesn'permits multi-statment",
|
||||
true,
|
||||
info,
|
||||
'08S01',
|
||||
Errors.ER_CLIENT_OPTION_INCOMPATIBILITY
|
||||
);
|
||||
}
|
||||
|
||||
if (opts.permitLocalInfile && (info.serverCapabilities & Capabilities.LOCAL_FILES) === 0) {
|
||||
return this.throwNewError(
|
||||
"Option `permitLocalInfile` enable, but server doesn'permits using local file",
|
||||
true,
|
||||
info,
|
||||
'08S01',
|
||||
Errors.ER_CLIENT_OPTION_INCOMPATIBILITY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
parseHandshakeInit(packet, out, opts, info) {
|
||||
if (packet.peek() === 0xff) {
|
||||
//in case that some host is not permit to connect server
|
||||
const authErr = packet.readError(info);
|
||||
authErr.fatal = true;
|
||||
return this.throwError(authErr, info);
|
||||
}
|
||||
|
||||
let handshake = new InitialHandshake(packet, info);
|
||||
this.ensureOptionCompatibility(opts, info);
|
||||
ClientCapabilities.init(opts, info);
|
||||
|
||||
if (opts.ssl) {
|
||||
if (info.serverCapabilities & Capabilities.SSL) {
|
||||
info.clientCapabilities |= Capabilities.SSL;
|
||||
SslRequest.send(this, out, info, opts);
|
||||
this._createSecureContext(
|
||||
function () {
|
||||
ClientHandshakeResponse.send(this, out, opts, handshake.pluginName, info);
|
||||
}.bind(this)
|
||||
);
|
||||
} else {
|
||||
return this.throwNewError(
|
||||
'Trying to connect with ssl, but ssl not enabled in the server',
|
||||
true,
|
||||
info,
|
||||
'08S01',
|
||||
Errors.ER_SERVER_SSL_DISABLED
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ClientHandshakeResponse.send(this, out, opts, handshake.pluginName, info);
|
||||
}
|
||||
this.onPacketReceive = this.handshakeResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast-path handshake results :
|
||||
* - if plugin was the one expected by server, server will send OK_Packet / ERR_Packet.
|
||||
* - if not, server send an AuthSwitchRequest packet, indicating the specific PLUGIN to use with this user.
|
||||
* dispatching to plugin handler then.
|
||||
*
|
||||
* @param packet current packet
|
||||
* @param out output buffer
|
||||
* @param opts options
|
||||
* @param info connection info
|
||||
* @returns {*} return null if authentication succeed, depending on plugin conversation if not finished
|
||||
*/
|
||||
handshakeResult(packet, out, opts, info) {
|
||||
const marker = packet.peek();
|
||||
switch (marker) {
|
||||
//*********************************************************************************************************
|
||||
//* AuthSwitchRequest packet
|
||||
//*********************************************************************************************************
|
||||
case 0xfe:
|
||||
this.plugin.onPacketReceive = null;
|
||||
this.plugin.emit('send_end');
|
||||
this.plugin.emit('end');
|
||||
this.dispatchAuthSwitchRequest(packet, out, opts, info);
|
||||
return;
|
||||
|
||||
//*********************************************************************************************************
|
||||
//* OK_Packet - authentication succeeded
|
||||
//*********************************************************************************************************
|
||||
case 0x00:
|
||||
packet.skip(1); //skip header
|
||||
packet.skipLengthCodedNumber(); //skip affected rows
|
||||
packet.skipLengthCodedNumber(); //skip last insert id
|
||||
info.status = packet.readUInt16();
|
||||
this.plugin.emit('send_end');
|
||||
return this.plugin.successEnd();
|
||||
|
||||
//*********************************************************************************************************
|
||||
//* ERR_Packet
|
||||
//*********************************************************************************************************
|
||||
case 0xff:
|
||||
const authErr = packet.readError(info, this.displaySql());
|
||||
authErr.fatal = true;
|
||||
return this.plugin.throwError(authErr, info);
|
||||
|
||||
//*********************************************************************************************************
|
||||
//* unexpected
|
||||
//*********************************************************************************************************
|
||||
default:
|
||||
this.throwNewError(
|
||||
'Unexpected type of packet during handshake phase : ' + marker,
|
||||
true,
|
||||
info,
|
||||
'42000',
|
||||
Errors.ER_AUTHENTICATION_BAD_PACKET
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle authentication switch request : dispatch to plugin handler.
|
||||
*
|
||||
* @param packet packet
|
||||
* @param out output writer
|
||||
* @param opts options
|
||||
* @param info connection information
|
||||
*/
|
||||
dispatchAuthSwitchRequest(packet, out, opts, info) {
|
||||
let pluginName, pluginData;
|
||||
if (info.clientCapabilities & Capabilities.PLUGIN_AUTH) {
|
||||
packet.skip(1); //header
|
||||
if (packet.remaining()) {
|
||||
//AuthSwitchRequest packet.
|
||||
pluginName = packet.readStringNullEnded();
|
||||
pluginData = packet.readBufferRemaining();
|
||||
} else {
|
||||
//OldAuthSwitchRequest
|
||||
pluginName = 'mysql_old_password';
|
||||
pluginData = info.seed.slice(0, 8);
|
||||
}
|
||||
} else {
|
||||
pluginName = packet.readStringNullEnded('cesu8');
|
||||
pluginData = packet.readBufferRemaining();
|
||||
}
|
||||
|
||||
try {
|
||||
this.plugin = Handshake.pluginHandler(
|
||||
pluginName,
|
||||
this.plugin.sequenceNo,
|
||||
this.plugin.compressSequenceNo,
|
||||
pluginData,
|
||||
info,
|
||||
opts,
|
||||
out,
|
||||
this.resolve,
|
||||
this.reject,
|
||||
this.handshakeResult.bind(this)
|
||||
);
|
||||
} catch (err) {
|
||||
this.reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.plugin) {
|
||||
this.reject(
|
||||
Errors.createError(
|
||||
"Client does not support authentication protocol '" +
|
||||
pluginName +
|
||||
"' requested by server. ",
|
||||
true,
|
||||
info,
|
||||
'08004',
|
||||
Errors.ER_AUTHENTICATION_PLUGIN_NOT_SUPPORTED
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this._addCommand(this.plugin, false);
|
||||
}
|
||||
}
|
||||
|
||||
static pluginHandler(
|
||||
pluginName,
|
||||
packSeq,
|
||||
compressPackSeq,
|
||||
pluginData,
|
||||
info,
|
||||
opts,
|
||||
out,
|
||||
authResolve,
|
||||
authReject,
|
||||
multiAuthResolver
|
||||
) {
|
||||
let pluginAuth;
|
||||
switch (pluginName) {
|
||||
case 'mysql_native_password':
|
||||
pluginAuth = require('./auth/native-password-auth.js');
|
||||
break;
|
||||
|
||||
case 'mysql_clear_password':
|
||||
pluginAuth = require('./auth/clear-password-auth.js');
|
||||
break;
|
||||
|
||||
case 'client_ed25519':
|
||||
pluginAuth = require('./auth/ed25519-password-auth.js');
|
||||
break;
|
||||
|
||||
case 'dialog':
|
||||
pluginAuth = require('./auth/pam-password-auth.js');
|
||||
break;
|
||||
|
||||
case 'sha256_password':
|
||||
if (!Handshake.ensureNodeVersion(11, 6, 0)) {
|
||||
throw Errors.createError(
|
||||
'sha256_password authentication plugin require node 11.6+',
|
||||
true,
|
||||
info,
|
||||
'08004',
|
||||
Errors.ER_MINIMUM_NODE_VERSION_REQUIRED
|
||||
);
|
||||
}
|
||||
pluginAuth = require('./auth/sha256-password-auth.js');
|
||||
break;
|
||||
|
||||
case 'caching_sha2_password':
|
||||
if (!Handshake.ensureNodeVersion(11, 6, 0)) {
|
||||
throw Errors.createError(
|
||||
'caching_sha2_password authentication plugin require node 11.6+',
|
||||
true,
|
||||
info,
|
||||
'08004',
|
||||
Errors.ER_MINIMUM_NODE_VERSION_REQUIRED
|
||||
);
|
||||
}
|
||||
pluginAuth = require('./auth/caching-sha2-password-auth.js');
|
||||
break;
|
||||
|
||||
//TODO "auth_gssapi_client"
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return new pluginAuth(
|
||||
packSeq,
|
||||
compressPackSeq,
|
||||
pluginData,
|
||||
authResolve,
|
||||
authReject,
|
||||
multiAuthResolver
|
||||
);
|
||||
}
|
||||
|
||||
static ensureNodeVersion(major, minor, patch) {
|
||||
const ver = process.versions.node.split('.');
|
||||
return (
|
||||
ver[0] > major ||
|
||||
(ver[0] === major && ver[1] > minor) ||
|
||||
(ver[0] === major && ver[1] === minor && ver[2] >= patch)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Handshake;
|
||||
74
node_modules/mariadb/lib/cmd/handshake/initial-handshake.js
generated
vendored
Normal file
74
node_modules/mariadb/lib/cmd/handshake/initial-handshake.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
|
||||
const Capabilities = require('../../const/capabilities');
|
||||
const ConnectionInformation = require('../../misc/connection-information');
|
||||
|
||||
/**
|
||||
* Parser server initial handshake.
|
||||
* see https://mariadb.com/kb/en/library/1-connecting-connecting/#initial-handshake-packet
|
||||
*/
|
||||
class InitialHandshake {
|
||||
constructor(packet, info) {
|
||||
//protocolVersion
|
||||
packet.skip(1);
|
||||
info.serverVersion = {};
|
||||
info.serverVersion.raw = packet.readStringNullEnded();
|
||||
info.threadId = packet.readUInt32();
|
||||
|
||||
let seed1 = packet.readBuffer(8);
|
||||
packet.skip(1); //reserved byte
|
||||
|
||||
let serverCapabilities = BigInt(packet.readUInt16());
|
||||
//skip characterSet
|
||||
packet.skip(1);
|
||||
info.status = packet.readUInt16();
|
||||
serverCapabilities += BigInt(packet.readUInt16()) << BigInt(16);
|
||||
|
||||
let saltLength = 0;
|
||||
if (serverCapabilities & Capabilities.PLUGIN_AUTH) {
|
||||
saltLength = Math.max(12, packet.readUInt8() - 9);
|
||||
} else {
|
||||
packet.skip(1);
|
||||
}
|
||||
if (serverCapabilities & Capabilities.MYSQL) {
|
||||
packet.skip(10);
|
||||
} else {
|
||||
packet.skip(6);
|
||||
serverCapabilities += BigInt(packet.readUInt32()) << BigInt(32);
|
||||
}
|
||||
|
||||
if (serverCapabilities & Capabilities.SECURE_CONNECTION) {
|
||||
let seed2 = packet.readBuffer(saltLength);
|
||||
info.seed = Buffer.concat([seed1, seed2]);
|
||||
} else {
|
||||
info.seed = seed1;
|
||||
}
|
||||
packet.skip(1);
|
||||
info.serverCapabilities = serverCapabilities;
|
||||
|
||||
/**
|
||||
* check for MariaDB 10.x replication hack , remove fake prefix if needed
|
||||
* MDEV-4088: in 10.0+, the real version string maybe prefixed with "5.5.5-",
|
||||
* to workaround bugs in Oracle MySQL replication
|
||||
**/
|
||||
|
||||
if (info.serverVersion.raw.startsWith('5.5.5-')) {
|
||||
info.serverVersion.mariaDb = true;
|
||||
info.serverVersion.raw = info.serverVersion.raw.substring('5.5.5-'.length);
|
||||
} else {
|
||||
//Support for MDEV-7780 faking server version
|
||||
info.serverVersion.mariaDb =
|
||||
info.serverVersion.raw.includes('MariaDB') ||
|
||||
(serverCapabilities & Capabilities.MYSQL) === BigInt(0);
|
||||
}
|
||||
|
||||
if (serverCapabilities & Capabilities.PLUGIN_AUTH) {
|
||||
this.pluginName = packet.readStringNullEnded();
|
||||
} else {
|
||||
this.pluginName = '';
|
||||
}
|
||||
ConnectionInformation.parseVersionString(info);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InitialHandshake;
|
||||
29
node_modules/mariadb/lib/cmd/handshake/ssl-request.js
generated
vendored
Normal file
29
node_modules/mariadb/lib/cmd/handshake/ssl-request.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
const Capabilities = require('../../const/capabilities');
|
||||
|
||||
/**
|
||||
* Send SSL Request packet.
|
||||
* see : https://mariadb.com/kb/en/library/1-connecting-connecting/#sslrequest-packet
|
||||
*
|
||||
* @param cmd current command
|
||||
* @param out output writer
|
||||
* @param info client information
|
||||
* @param opts connection options
|
||||
*/
|
||||
module.exports.send = function sendSSLRequest(cmd, out, info, opts) {
|
||||
out.startPacket(cmd);
|
||||
out.writeInt32(Number(info.clientCapabilities & BigInt(0xffffffff)));
|
||||
out.writeInt32(1024 * 1024 * 1024); // max packet size
|
||||
out.writeInt8(opts.collation.index);
|
||||
for (let i = 0; i < 19; i++) {
|
||||
out.writeInt8(0);
|
||||
}
|
||||
|
||||
if (info.serverCapabilities & Capabilities.MYSQL) {
|
||||
out.writeInt32(0);
|
||||
} else {
|
||||
out.writeInt32(Number(info.clientCapabilities >> BigInt(32)));
|
||||
}
|
||||
|
||||
out.flushBuffer(true);
|
||||
};
|
||||
52
node_modules/mariadb/lib/cmd/ping.js
generated
vendored
Normal file
52
node_modules/mariadb/lib/cmd/ping.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const Command = require('./command');
|
||||
const Errors = require('../misc/errors');
|
||||
|
||||
/**
|
||||
* send a COM_PING: permits sending a packet containing one byte to check that the connection is active.
|
||||
* see https://mariadb.com/kb/en/library/com_ping/
|
||||
*/
|
||||
class Ping extends Command {
|
||||
constructor(resolve, reject) {
|
||||
super(resolve, reject);
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x0e);
|
||||
out.flushBuffer(true);
|
||||
this.emit('send_end');
|
||||
this.onPacketReceive = this.readPingResponsePacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read ping response packet.
|
||||
* packet can be :
|
||||
* - an ERR_Packet
|
||||
* - a OK_Packet
|
||||
*
|
||||
* @param packet query response
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection info
|
||||
*/
|
||||
readPingResponsePacket(packet, out, opts, info) {
|
||||
if (packet.peek() !== 0x00) {
|
||||
return this.throwNewError(
|
||||
'unexpected packet',
|
||||
false,
|
||||
info,
|
||||
'42000',
|
||||
Errors.ER_PING_BAD_PACKET
|
||||
);
|
||||
}
|
||||
packet.skip(1); //skip header
|
||||
packet.skipLengthCodedNumber(); //affected rows
|
||||
packet.skipLengthCodedNumber(); //insert ids
|
||||
info.status = packet.readUInt16();
|
||||
this.successEnd(null);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Ping;
|
||||
253
node_modules/mariadb/lib/cmd/query.js
generated
vendored
Normal file
253
node_modules/mariadb/lib/cmd/query.js
generated
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
'use strict';
|
||||
|
||||
const CommonText = require('./common-text-cmd');
|
||||
const Errors = require('../misc/errors');
|
||||
const Parse = require('../misc/parse');
|
||||
const QUOTE = 0x27;
|
||||
|
||||
/**
|
||||
* Protocol COM_QUERY
|
||||
* see : https://mariadb.com/kb/en/library/com_query/
|
||||
*/
|
||||
class Query extends CommonText {
|
||||
constructor(resolve, reject, options, connOpts, sql, values) {
|
||||
super(resolve, reject, options, connOpts, sql, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send COM_QUERY
|
||||
*
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
*/
|
||||
start(out, opts, info) {
|
||||
if (!this.initialValues) {
|
||||
//shortcut if no parameters
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x03);
|
||||
if (!this.handleTimeout(out, info)) return;
|
||||
out.writeString(this.sql);
|
||||
out.flushBuffer(true);
|
||||
this.emit('send_end');
|
||||
return (this.onPacketReceive = this.readResponsePacket);
|
||||
}
|
||||
|
||||
if (this.opts.namedPlaceholders) {
|
||||
try {
|
||||
const parsed = Parse.splitQueryPlaceholder(
|
||||
this.sql,
|
||||
info,
|
||||
this.initialValues,
|
||||
this.displaySql.bind(this)
|
||||
);
|
||||
this.queryParts = parsed.parts;
|
||||
this.values = parsed.values;
|
||||
} catch (err) {
|
||||
this.emit('send_end');
|
||||
return this.throwError(err, info);
|
||||
}
|
||||
} else {
|
||||
this.queryParts = Parse.splitQuery(this.sql);
|
||||
this.values = Array.isArray(this.initialValues) ? this.initialValues : [this.initialValues];
|
||||
if (!this.validateParameters(info)) return;
|
||||
}
|
||||
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x03);
|
||||
if (!this.handleTimeout(out, info)) return;
|
||||
out.writeString(this.queryParts[0]);
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
|
||||
//********************************************
|
||||
// send params
|
||||
//********************************************
|
||||
const len = this.queryParts.length;
|
||||
for (let i = 1; i < len; i++) {
|
||||
const value = this.values[i - 1];
|
||||
|
||||
if (
|
||||
value !== null &&
|
||||
typeof value === 'object' &&
|
||||
typeof value.pipe === 'function' &&
|
||||
typeof value.read === 'function'
|
||||
) {
|
||||
this.sending = true;
|
||||
//********************************************
|
||||
// param is stream,
|
||||
// now all params will be written by event
|
||||
//********************************************
|
||||
this.registerStreamSendEvent(out, info);
|
||||
this.currentParam = i;
|
||||
out.writeInt8(QUOTE); //'
|
||||
|
||||
value.on('data', function (chunk) {
|
||||
out.writeBufferEscape(chunk);
|
||||
});
|
||||
|
||||
value.on(
|
||||
'end',
|
||||
function () {
|
||||
out.writeInt8(QUOTE); //'
|
||||
out.writeString(this.queryParts[this.currentParam++]);
|
||||
this.paramWritten();
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
return;
|
||||
} else {
|
||||
//********************************************
|
||||
// param isn't stream. directly write in buffer
|
||||
//********************************************
|
||||
this.writeParam(out, value, this.opts, info);
|
||||
out.writeString(this.queryParts[i]);
|
||||
}
|
||||
}
|
||||
out.flushBuffer(true);
|
||||
this.emit('send_end');
|
||||
}
|
||||
|
||||
/**
|
||||
* If timeout is set, prepend query with SET STATEMENT max_statement_time=xx FOR, or throw an error
|
||||
* @param out buffer
|
||||
* @param info server information
|
||||
* @returns {boolean} false if an error has been thrown
|
||||
*/
|
||||
handleTimeout(out, info) {
|
||||
if (this.opts.timeout) {
|
||||
if (info.isMariaDB()) {
|
||||
if (info.hasMinVersion(10, 1, 2)) {
|
||||
out.writeString('SET STATEMENT max_statement_time=' + this.opts.timeout / 1000 + ' FOR ');
|
||||
return true;
|
||||
} else {
|
||||
const err = Errors.createError(
|
||||
'Cannot use timeout for MariaDB server before 10.1.2. timeout value: ' +
|
||||
this.opts.timeout,
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_TIMEOUT_NOT_SUPPORTED
|
||||
);
|
||||
this.emit('send_end');
|
||||
this.throwError(err, info);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
//not available for MySQL
|
||||
// max_execution time exist, but only for select, and as hint
|
||||
const err = Errors.createError(
|
||||
'Cannot use timeout for MySQL server. timeout value: ' + this.opts.timeout,
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_TIMEOUT_NOT_SUPPORTED
|
||||
);
|
||||
this.emit('send_end');
|
||||
this.throwError(err, info);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that parameters exists and are defined.
|
||||
*
|
||||
* @param info connection info
|
||||
* @returns {boolean} return false if any error occur.
|
||||
*/
|
||||
validateParameters(info) {
|
||||
//validate parameter size.
|
||||
if (this.queryParts.length - 1 > this.values.length) {
|
||||
this.emit('send_end');
|
||||
this.throwNewError(
|
||||
'Parameter at position ' + (this.values.length + 1) + ' is not set\n' + this.displaySql(),
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_MISSING_PARAMETER
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
//validate parameter is defined.
|
||||
for (let i = 0; i < this.queryParts.length - 1; i++) {
|
||||
if (this.values[i] === undefined) {
|
||||
this.emit('send_end');
|
||||
this.throwNewError(
|
||||
'Parameter at position ' + (i + 1) + ' is undefined\n' + this.displaySql(),
|
||||
false,
|
||||
info,
|
||||
'HY000',
|
||||
Errors.ER_PARAMETER_UNDEFINED
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define params events.
|
||||
* Each parameter indicate that he is written to socket,
|
||||
* emitting event so next stream parameter can be written.
|
||||
*/
|
||||
registerStreamSendEvent(out, info) {
|
||||
// note : Implementation use recursive calls, but stack won't never get near v8 max call stack size
|
||||
//since event launched for stream parameter only
|
||||
this.paramWritten = function () {
|
||||
while (true) {
|
||||
if (this.currentParam === this.queryParts.length) {
|
||||
//********************************************
|
||||
// all parameters are written.
|
||||
// flush packet
|
||||
//********************************************
|
||||
out.flushBuffer(true);
|
||||
this.sending = false;
|
||||
this.emit('send_end');
|
||||
return;
|
||||
} else {
|
||||
const value = this.values[this.currentParam - 1];
|
||||
|
||||
if (value === null) {
|
||||
out.writeStringAscii('NULL');
|
||||
out.writeString(this.queryParts[this.currentParam++]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof value === 'object' &&
|
||||
typeof value.pipe === 'function' &&
|
||||
typeof value.read === 'function'
|
||||
) {
|
||||
//********************************************
|
||||
// param is stream,
|
||||
//********************************************
|
||||
out.writeInt8(QUOTE);
|
||||
value.once(
|
||||
'end',
|
||||
function () {
|
||||
out.writeInt8(QUOTE);
|
||||
out.writeString(this.queryParts[this.currentParam++]);
|
||||
this.paramWritten();
|
||||
}.bind(this)
|
||||
);
|
||||
value.on('data', function (chunk) {
|
||||
out.writeBufferEscape(chunk);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
//********************************************
|
||||
// param isn't stream. directly write in buffer
|
||||
//********************************************
|
||||
this.writeParam(out, value, this.opts, info);
|
||||
out.writeString(this.queryParts[this.currentParam++]);
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Query;
|
||||
28
node_modules/mariadb/lib/cmd/quit.js
generated
vendored
Normal file
28
node_modules/mariadb/lib/cmd/quit.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const Command = require('./command');
|
||||
|
||||
/**
|
||||
* Quit (close connection)
|
||||
* see https://mariadb.com/kb/en/library/com_quit/
|
||||
*/
|
||||
class Quit extends Command {
|
||||
constructor(resolve, reject) {
|
||||
super(resolve, reject);
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x01);
|
||||
out.flushBuffer(true);
|
||||
this.emit('send_end');
|
||||
this.successEnd();
|
||||
this.onPacketReceive = this.skipResults;
|
||||
}
|
||||
|
||||
skipResults(packet, out, opts, info) {
|
||||
//deliberately empty, if server send answer
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Quit;
|
||||
54
node_modules/mariadb/lib/cmd/reset.js
generated
vendored
Normal file
54
node_modules/mariadb/lib/cmd/reset.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
const Command = require('./command');
|
||||
const Errors = require('../misc/errors');
|
||||
|
||||
/**
|
||||
* send a COM_RESET_CONNECTION: permits to reset a connection without re-authentication.
|
||||
* see https://mariadb.com/kb/en/library/com_reset_connection/
|
||||
*/
|
||||
class Reset extends Command {
|
||||
constructor(resolve, reject) {
|
||||
super(resolve, reject);
|
||||
}
|
||||
|
||||
start(out, opts, info) {
|
||||
out.startPacket(this);
|
||||
out.writeInt8(0x1f);
|
||||
out.flushBuffer(true);
|
||||
this.emit('send_end');
|
||||
this.onPacketReceive = this.readResetResponsePacket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read response packet.
|
||||
* packet can be :
|
||||
* - an ERR_Packet
|
||||
* - a OK_Packet
|
||||
*
|
||||
* @param packet query response
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection info
|
||||
*/
|
||||
readResetResponsePacket(packet, out, opts, info) {
|
||||
if (packet.peek() !== 0x00) {
|
||||
return this.throwNewError(
|
||||
'unexpected packet',
|
||||
false,
|
||||
info,
|
||||
'42000',
|
||||
Errors.ER_RESET_BAD_PACKET
|
||||
);
|
||||
}
|
||||
|
||||
packet.skip(1); //skip header
|
||||
packet.skipLengthCodedNumber(); //affected rows
|
||||
packet.skipLengthCodedNumber(); //insert ids
|
||||
|
||||
info.status = packet.readUInt16();
|
||||
this.successEnd(null);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Reset;
|
||||
605
node_modules/mariadb/lib/cmd/resultset.js
generated
vendored
Normal file
605
node_modules/mariadb/lib/cmd/resultset.js
generated
vendored
Normal file
@@ -0,0 +1,605 @@
|
||||
'use strict';
|
||||
|
||||
const Command = require('./command');
|
||||
const ServerStatus = require('../const/server-status');
|
||||
const ColumnDefinition = require('./column-definition');
|
||||
const Errors = require('../misc/errors');
|
||||
const fs = require('fs');
|
||||
const Parse = require('../misc/parse');
|
||||
|
||||
/**
|
||||
* handle COM_QUERY / COM_STMT_EXECUTE results
|
||||
* see : https://mariadb.com/kb/en/library/4-server-response-packets/
|
||||
*/
|
||||
class ResultSet extends Command {
|
||||
constructor(resolve, reject) {
|
||||
super(resolve, reject);
|
||||
this._responseIndex = 0;
|
||||
this._rows = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read Query response packet.
|
||||
* packet can be :
|
||||
* - a result-set
|
||||
* - an ERR_Packet
|
||||
* - a OK_Packet
|
||||
* - LOCAL_INFILE Packet
|
||||
*
|
||||
* @param packet query response
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection info
|
||||
*/
|
||||
readResponsePacket(packet, out, opts, info) {
|
||||
switch (packet.peek()) {
|
||||
//*********************************************************************************************************
|
||||
//* OK response
|
||||
//*********************************************************************************************************
|
||||
case 0x00:
|
||||
return this.readOKPacket(packet, out, opts, info);
|
||||
|
||||
//*********************************************************************************************************
|
||||
//* ERROR response
|
||||
//*********************************************************************************************************
|
||||
case 0xff:
|
||||
const err = packet.readError(info, this.displaySql(), this.stack);
|
||||
//force in transaction status, since query will have created a transaction if autocommit is off
|
||||
//goal is to avoid unnecessary COMMIT/ROLLBACK.
|
||||
info.status |= ServerStatus.STATUS_IN_TRANS;
|
||||
return this.throwError(err, info);
|
||||
|
||||
//*********************************************************************************************************
|
||||
//* LOCAL INFILE response
|
||||
//*********************************************************************************************************
|
||||
case 0xfb:
|
||||
return this.readLocalInfile(packet, out, opts, info);
|
||||
|
||||
//*********************************************************************************************************
|
||||
//* ResultSet
|
||||
//*********************************************************************************************************
|
||||
default:
|
||||
return this.readResultSet(packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read result-set packets :
|
||||
* see https://mariadb.com/kb/en/library/resultset/
|
||||
*
|
||||
* @param packet Column count packet
|
||||
* @returns {ResultSet.readColumn} next packet handler
|
||||
*/
|
||||
readResultSet(packet) {
|
||||
this._columnCount = packet.readUnsignedLength();
|
||||
this._getValue = this.opts.typeCast ? this.readCastValue : this.readRowData;
|
||||
this._rows.push([]);
|
||||
this._columns = [];
|
||||
|
||||
this.onPacketReceive = this.readColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign global configuration option used by result-set to current query option.
|
||||
* a little faster than Object.assign() since doest copy all information
|
||||
*
|
||||
* @param connOpts connection global configuration
|
||||
* @param cmdOpts specific command options
|
||||
*/
|
||||
configAssign(connOpts, cmdOpts) {
|
||||
if (!cmdOpts) {
|
||||
this.opts = connOpts;
|
||||
return;
|
||||
}
|
||||
this.opts = {
|
||||
timeout: cmdOpts.timeout,
|
||||
autoJsonMap: connOpts.autoJsonMap,
|
||||
arrayParenthesis: connOpts.arrayParenthesis,
|
||||
supportBigInt:
|
||||
cmdOpts.supportBigInt != undefined ? cmdOpts.supportBigInt : connOpts.supportBigInt,
|
||||
checkDuplicate:
|
||||
cmdOpts.checkDuplicate != undefined ? cmdOpts.checkDuplicate : connOpts.checkDuplicate,
|
||||
typeCast: cmdOpts.typeCast != undefined ? cmdOpts.typeCast : connOpts.typeCast,
|
||||
rowsAsArray: cmdOpts.rowsAsArray != undefined ? cmdOpts.rowsAsArray : connOpts.rowsAsArray,
|
||||
nestTables: cmdOpts.nestTables != undefined ? cmdOpts.nestTables : connOpts.nestTables,
|
||||
dateStrings: cmdOpts.dateStrings != undefined ? cmdOpts.dateStrings : connOpts.dateStrings,
|
||||
tz: cmdOpts.tz != undefined ? cmdOpts.tz : connOpts.tz,
|
||||
pipelining: connOpts.pipelining,
|
||||
localTz: cmdOpts.localTz != undefined ? cmdOpts.localTz : connOpts.localTz,
|
||||
namedPlaceholders:
|
||||
cmdOpts.namedPlaceholders != undefined
|
||||
? cmdOpts.namedPlaceholders
|
||||
: connOpts.namedPlaceholders,
|
||||
maxAllowedPacket:
|
||||
cmdOpts.maxAllowedPacket != undefined
|
||||
? cmdOpts.maxAllowedPacket
|
||||
: connOpts.maxAllowedPacket,
|
||||
supportBigNumbers:
|
||||
cmdOpts.supportBigNumbers != undefined
|
||||
? cmdOpts.supportBigNumbers
|
||||
: connOpts.supportBigNumbers,
|
||||
permitSetMultiParamEntries:
|
||||
cmdOpts.permitSetMultiParamEntries != undefined
|
||||
? cmdOpts.permitSetMultiParamEntries
|
||||
: connOpts.permitSetMultiParamEntries,
|
||||
bigNumberStrings:
|
||||
cmdOpts.bigNumberStrings != undefined ? cmdOpts.bigNumberStrings : connOpts.bigNumberStrings
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Read OK_Packet.
|
||||
* see https://mariadb.com/kb/en/library/ok_packet/
|
||||
*
|
||||
* @param packet OK_Packet
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
* @param out output writer
|
||||
* @returns {*} null or {Resultset.readResponsePacket} in case of multi-result-set
|
||||
*/
|
||||
readOKPacket(packet, out, opts, info) {
|
||||
const okPacket = Command.parseOkPacket(packet, out, opts, info);
|
||||
this._rows.push(okPacket);
|
||||
|
||||
if (info.status & ServerStatus.MORE_RESULTS_EXISTS) {
|
||||
this._responseIndex++;
|
||||
return (this.onPacketReceive = this.readResponsePacket);
|
||||
}
|
||||
this.success(this._responseIndex === 0 ? this._rows[0] : this._rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read COM_STMT_PREPARE response Packet.
|
||||
* see https://mariadb.com/kb/en/library/com_stmt_prepare/#com_stmt_prepare-response
|
||||
*
|
||||
* @param packet COM_STMT_PREPARE_OK packet
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
* @param out output writer
|
||||
* @returns {*} null or {Resultset.readResponsePacket} in case of multi-result-set
|
||||
*/
|
||||
readPrepareResultPacket(packet, out, opts, info) {
|
||||
switch (packet.peek()) {
|
||||
//*********************************************************************************************************
|
||||
//* OK response
|
||||
//*********************************************************************************************************
|
||||
case 0x00:
|
||||
packet.skip(1); //skip header
|
||||
this.statementId = packet.readInt32();
|
||||
this.columnNo = packet.readUInt16();
|
||||
this.parameterNo = packet.readUInt16();
|
||||
|
||||
if (this.columnNo > 0) return (this.onPacketReceive = this.skipColumnsPacket);
|
||||
if (this.parameterNo > 0) return (this.onPacketReceive = this.skipParameterPacket);
|
||||
return this.success();
|
||||
|
||||
//*********************************************************************************************************
|
||||
//* ERROR response
|
||||
//*********************************************************************************************************
|
||||
case 0xff:
|
||||
const err = packet.readError(info, this.displaySql(), this.stack);
|
||||
//force in transaction status, since query will have created a transaction if autocommit is off
|
||||
//goal is to avoid unnecessary COMMIT/ROLLBACK.
|
||||
info.status |= ServerStatus.STATUS_IN_TRANS;
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
return this.throwError(err, info);
|
||||
|
||||
//*********************************************************************************************************
|
||||
//* Unexpected response
|
||||
//*********************************************************************************************************
|
||||
default:
|
||||
info.status |= ServerStatus.STATUS_IN_TRANS;
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
return this.throwError(Errors.ER_UNEXPECTED_PACKET, info);
|
||||
}
|
||||
}
|
||||
|
||||
skipColumnsPacket(packet, out, opts, info) {
|
||||
this.columnNo--;
|
||||
if (this.columnNo === 0) {
|
||||
if (info.eofDeprecated) {
|
||||
if (this.parameterNo > 0) return (this.onPacketReceive = this.skipParameterPacket);
|
||||
this.success();
|
||||
}
|
||||
return (this.onPacketReceive = this.skipEofPacket);
|
||||
}
|
||||
}
|
||||
|
||||
skipEofPacket(packet, out, opts, info) {
|
||||
if (this.parameterNo > 0) return (this.onPacketReceive = this.skipParameterPacket);
|
||||
this.success();
|
||||
}
|
||||
|
||||
skipParameterPacket(packet, out, opts, info) {
|
||||
this.parameterNo--;
|
||||
if (this.parameterNo === 0) {
|
||||
if (info.eofDeprecated) return this.success();
|
||||
return (this.onPacketReceive = this.skipEofPacket);
|
||||
}
|
||||
}
|
||||
|
||||
success(val) {
|
||||
this.successEnd(val);
|
||||
this._columns = null;
|
||||
this._rows = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read column information metadata
|
||||
* see https://mariadb.com/kb/en/library/resultset/#column-definition-packet
|
||||
*
|
||||
* @param packet column definition packet
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
* @returns {*}
|
||||
*/
|
||||
readColumn(packet, out, opts, info) {
|
||||
if (this._columns.length !== this._columnCount) {
|
||||
this._columns.push(new ColumnDefinition(packet, info));
|
||||
}
|
||||
|
||||
// last column
|
||||
if (this._columns.length === this._columnCount) {
|
||||
if (this.opts.rowsAsArray) {
|
||||
this.parseRow = this.parseRowAsArray;
|
||||
} else {
|
||||
this.tableHeader = new Array(this._columnCount);
|
||||
if (this.opts.nestTables) {
|
||||
this.parseRow = this.parseRowStd;
|
||||
if (typeof this.opts.nestTables === 'string') {
|
||||
for (let i = 0; i < this._columnCount; i++) {
|
||||
this.tableHeader[i] =
|
||||
this._columns[i].table() + this.opts.nestTables + this._columns[i].name();
|
||||
}
|
||||
this.checkDuplicates();
|
||||
} else if (this.opts.nestTables === true) {
|
||||
this.parseRow = this.parseRowNested;
|
||||
for (let i = 0; i < this._columnCount; i++) {
|
||||
this.tableHeader[i] = [this._columns[i].table(), this._columns[i].name()];
|
||||
}
|
||||
this.checkNestTablesDuplicates();
|
||||
}
|
||||
} else {
|
||||
this.parseRow = this.parseRowStd;
|
||||
for (let i = 0; i < this._columnCount; i++) {
|
||||
this.tableHeader[i] = this._columns[i].name();
|
||||
}
|
||||
this.checkDuplicates();
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('fields', this._columns);
|
||||
|
||||
return (this.onPacketReceive = info.eofDeprecated
|
||||
? this.readResultSetRow
|
||||
: this.readIntermediateEOF);
|
||||
}
|
||||
}
|
||||
|
||||
checkDuplicates() {
|
||||
if (this.opts.checkDuplicate) {
|
||||
for (let i = 0; i < this._columnCount; i++) {
|
||||
if (this.tableHeader.indexOf(this.tableHeader[i], i + 1) > 0) {
|
||||
const dupes = this.tableHeader.reduce(
|
||||
(acc, v, i, arr) =>
|
||||
arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc,
|
||||
[]
|
||||
);
|
||||
this.throwUnexpectedError(
|
||||
'Error in results, duplicate field name `' +
|
||||
dupes[0] +
|
||||
'`.\n' +
|
||||
'(see option `checkDuplicate`)',
|
||||
false,
|
||||
null,
|
||||
'42000',
|
||||
Errors.ER_DUPLICATE_FIELD
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkNestTablesDuplicates() {
|
||||
if (this.opts.checkDuplicate) {
|
||||
for (let i = 0; i < this._columnCount; i++) {
|
||||
for (let j = 0; j < i; j++) {
|
||||
if (
|
||||
this.tableHeader[j][0] === this.tableHeader[i][0] &&
|
||||
this.tableHeader[j][1] === this.tableHeader[i][1]
|
||||
) {
|
||||
this.throwUnexpectedError(
|
||||
'Error in results, duplicate field name `' +
|
||||
this.tableHeader[i][0] +
|
||||
'`.`' +
|
||||
this.tableHeader[i][1] +
|
||||
'`\n' +
|
||||
'(see option `checkDuplicate`)',
|
||||
false,
|
||||
null,
|
||||
'42000',
|
||||
Errors.ER_DUPLICATE_FIELD
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read intermediate EOF.
|
||||
* _only for server before MariaDB 10.2 / MySQL 5.7 that doesn't have CLIENT_DEPRECATE_EOF capability_
|
||||
* see https://mariadb.com/kb/en/library/eof_packet/
|
||||
*
|
||||
* @param packet EOF Packet
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
* @returns {*}
|
||||
*/
|
||||
readIntermediateEOF(packet, out, opts, info) {
|
||||
if (packet.peek() !== 0xfe) {
|
||||
return this.throwNewError(
|
||||
'Error in protocol, expected EOF packet',
|
||||
true,
|
||||
info,
|
||||
'42000',
|
||||
Errors.ER_EOF_EXPECTED
|
||||
);
|
||||
}
|
||||
|
||||
//before MySQL 5.7.5, last EOF doesn't contain the good flag SERVER_MORE_RESULTS_EXISTS
|
||||
//for OUT parameters. It must be checked here
|
||||
//(5.7.5 does have the CLIENT_DEPRECATE_EOF capability, so this packet in not even send)
|
||||
packet.skip(3);
|
||||
info.status = packet.readUInt16();
|
||||
this.isOutParameter = info.status & ServerStatus.PS_OUT_PARAMS;
|
||||
|
||||
this.onPacketReceive = this.readResultSetRow;
|
||||
}
|
||||
|
||||
handleNewRows(row) {
|
||||
this._rows[this._responseIndex].push(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if packet is result-set end = EOF of OK_Packet with EOF header according to CLIENT_DEPRECATE_EOF capability
|
||||
* or a result-set row
|
||||
*
|
||||
* @param packet current packet
|
||||
* @param out output writer
|
||||
* @param opts connection options
|
||||
* @param info connection information
|
||||
* @returns {*}
|
||||
*/
|
||||
readResultSetRow(packet, out, opts, info) {
|
||||
if (packet.peek() >= 0xfe) {
|
||||
if (packet.peek() === 0xff) {
|
||||
const err = packet.readError(info, this.displaySql(), this.stack);
|
||||
//force in transaction status, since query will have created a transaction if autocommit is off
|
||||
//goal is to avoid unnecessary COMMIT/ROLLBACK.
|
||||
info.status |= ServerStatus.STATUS_IN_TRANS;
|
||||
return this.throwError(err, info);
|
||||
}
|
||||
|
||||
if (
|
||||
(!info.eofDeprecated && packet.length() < 13) ||
|
||||
(info.eofDeprecated && packet.length() < 0xffffff)
|
||||
) {
|
||||
if (!info.eofDeprecated) {
|
||||
packet.skip(3);
|
||||
info.status = packet.readUInt16();
|
||||
} else {
|
||||
packet.skip(1); //skip header
|
||||
packet.skipLengthCodedNumber(); //skip update count
|
||||
packet.skipLengthCodedNumber(); //skip insert id
|
||||
info.status = packet.readUInt16();
|
||||
}
|
||||
|
||||
if (opts.metaAsArray) {
|
||||
//return promise object as array :
|
||||
// example for SELECT 1 =>
|
||||
// [
|
||||
// [ {"1": 1} ], //rows
|
||||
// [ColumnDefinition] //meta
|
||||
// ]
|
||||
if (!this._meta) {
|
||||
this._meta = new Array(this._responseIndex);
|
||||
}
|
||||
|
||||
this._meta[this._responseIndex] = this._columns;
|
||||
|
||||
if (info.status & ServerStatus.MORE_RESULTS_EXISTS || this.isOutParameter) {
|
||||
this._responseIndex++;
|
||||
return (this.onPacketReceive = this.readResponsePacket);
|
||||
}
|
||||
this.success(
|
||||
this._responseIndex === 0 ? [this._rows[0], this._meta[0]] : [this._rows, this._meta]
|
||||
);
|
||||
} else {
|
||||
//return promise object as rows that have meta property :
|
||||
// example for SELECT 1 =>
|
||||
// [
|
||||
// {"1": 1},
|
||||
// meta: [ColumnDefinition]
|
||||
// ]
|
||||
this._rows[this._responseIndex].meta = this._columns;
|
||||
if (info.status & ServerStatus.MORE_RESULTS_EXISTS || this.isOutParameter) {
|
||||
this._responseIndex++;
|
||||
return (this.onPacketReceive = this.readResponsePacket);
|
||||
}
|
||||
this.success(this._responseIndex === 0 ? this._rows[0] : this._rows);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const row = this.parseRow(this._columns, packet, opts);
|
||||
this.handleNewRows(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display current SQL with parameters (truncated if too big)
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
displaySql() {
|
||||
if (this.opts && this.initialValues) {
|
||||
if (this.sql.length > this.opts.debugLen) {
|
||||
return 'sql: ' + this.sql.substring(0, this.opts.debugLen) + '...';
|
||||
}
|
||||
|
||||
let sqlMsg = 'sql: ' + this.sql + ' - parameters:';
|
||||
return this.logParameters(sqlMsg, this.initialValues);
|
||||
}
|
||||
return 'sql: ' + this.sql + ' - parameters:[]';
|
||||
}
|
||||
|
||||
logParameters(sqlMsg, values) {
|
||||
if (this.opts.namedPlaceholders) {
|
||||
sqlMsg += '{';
|
||||
let first = true;
|
||||
for (let key in values) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sqlMsg += ',';
|
||||
}
|
||||
sqlMsg += "'" + key + "':";
|
||||
let param = values[key];
|
||||
sqlMsg = ResultSet.logParam(sqlMsg, param);
|
||||
if (sqlMsg.length > this.opts.debugLen) {
|
||||
sqlMsg = sqlMsg.substr(0, this.opts.debugLen) + '...';
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlMsg += '}';
|
||||
} else {
|
||||
sqlMsg += '[';
|
||||
if (Array.isArray(values)) {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
if (i !== 0) sqlMsg += ',';
|
||||
let param = values[i];
|
||||
sqlMsg = ResultSet.logParam(sqlMsg, param);
|
||||
if (sqlMsg.length > this.opts.debugLen) {
|
||||
sqlMsg = sqlMsg.substr(0, this.opts.debugLen) + '...';
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sqlMsg = ResultSet.logParam(sqlMsg, values);
|
||||
if (sqlMsg.length > this.opts.debugLen) {
|
||||
sqlMsg = sqlMsg.substr(0, this.opts.debugLen) + '...';
|
||||
}
|
||||
}
|
||||
sqlMsg += ']';
|
||||
}
|
||||
return sqlMsg;
|
||||
}
|
||||
|
||||
readLocalInfile(packet, out, opts, info) {
|
||||
packet.skip(1); //skip header
|
||||
out.startPacket(this);
|
||||
|
||||
const fileName = packet.readStringRemaining();
|
||||
|
||||
if (!Parse.validateFileName(this.sql, this.initialValues, fileName)) {
|
||||
out.writeEmptyPacket();
|
||||
const error = Errors.createError(
|
||||
"LOCAL INFILE wrong filename. '" +
|
||||
fileName +
|
||||
"' doesn't correspond to query " +
|
||||
this.sql +
|
||||
'. Query cancelled. Check for malicious server / proxy',
|
||||
false,
|
||||
info,
|
||||
'45034',
|
||||
Errors.ER_LOCAL_INFILE_WRONG_FILENAME
|
||||
);
|
||||
|
||||
process.nextTick(this.reject, error);
|
||||
this.reject = null;
|
||||
this.resolve = null;
|
||||
return (this.onPacketReceive = this.readResponsePacket);
|
||||
}
|
||||
|
||||
// this.sequenceNo = 2;
|
||||
// this.compressSequenceNo = 2;
|
||||
const stream = fs.createReadStream(fileName);
|
||||
stream.on('error', (err) => {
|
||||
out.writeEmptyPacket();
|
||||
const error = Errors.createError(
|
||||
'LOCAL INFILE command failed: ' + err.message,
|
||||
false,
|
||||
info,
|
||||
'22000',
|
||||
Errors.ER_LOCAL_INFILE_NOT_READABLE
|
||||
);
|
||||
process.nextTick(this.reject, error);
|
||||
this.reject = null;
|
||||
this.resolve = null;
|
||||
});
|
||||
stream.on('data', (chunk) => {
|
||||
out.writeBuffer(chunk, 0, chunk.length);
|
||||
});
|
||||
stream.on('end', () => {
|
||||
if (!out.isEmpty()) {
|
||||
out.flushBuffer(false);
|
||||
}
|
||||
out.writeEmptyPacket();
|
||||
});
|
||||
this.onPacketReceive = this.readResponsePacket;
|
||||
}
|
||||
|
||||
static logParam(sqlMsg, param) {
|
||||
if (param === undefined || param === null) {
|
||||
sqlMsg += param === undefined ? 'undefined' : 'null';
|
||||
} else {
|
||||
switch (param.constructor.name) {
|
||||
case 'Buffer':
|
||||
sqlMsg += '0x' + param.toString('hex', 0, Math.min(1024, param.length)) + '';
|
||||
break;
|
||||
|
||||
case 'String':
|
||||
sqlMsg += "'" + param + "'";
|
||||
break;
|
||||
|
||||
case 'Date':
|
||||
sqlMsg += getStringDate(param);
|
||||
break;
|
||||
|
||||
case 'Object':
|
||||
sqlMsg += JSON.stringify(param);
|
||||
break;
|
||||
|
||||
default:
|
||||
sqlMsg += param.toString();
|
||||
}
|
||||
}
|
||||
return sqlMsg;
|
||||
}
|
||||
}
|
||||
|
||||
function getStringDate(param) {
|
||||
return (
|
||||
"'" +
|
||||
('00' + (param.getMonth() + 1)).slice(-2) +
|
||||
'/' +
|
||||
('00' + param.getDate()).slice(-2) +
|
||||
'/' +
|
||||
param.getFullYear() +
|
||||
' ' +
|
||||
('00' + param.getHours()).slice(-2) +
|
||||
':' +
|
||||
('00' + param.getMinutes()).slice(-2) +
|
||||
':' +
|
||||
('00' + param.getSeconds()).slice(-2) +
|
||||
'.' +
|
||||
('000' + param.getMilliseconds()).slice(-3) +
|
||||
"'"
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = ResultSet;
|
||||
45
node_modules/mariadb/lib/cmd/stream.js
generated
vendored
Normal file
45
node_modules/mariadb/lib/cmd/stream.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
'use strict';
|
||||
|
||||
const Query = require('./query');
|
||||
const { Readable } = require('stream');
|
||||
|
||||
/**
|
||||
* Protocol COM_QUERY with streaming events.
|
||||
* see : https://mariadb.com/kb/en/library/com_query/
|
||||
*/
|
||||
class Stream extends Query {
|
||||
constructor(cmdOpts, connOpts, sql, values, socket) {
|
||||
super(
|
||||
() => {},
|
||||
() => {},
|
||||
cmdOpts,
|
||||
connOpts,
|
||||
sql,
|
||||
values
|
||||
);
|
||||
this.socket = socket;
|
||||
this.inStream = new Readable({
|
||||
objectMode: true,
|
||||
read: () => {}
|
||||
});
|
||||
|
||||
this.on('fields', function (meta) {
|
||||
this.inStream.emit('fields', meta);
|
||||
});
|
||||
|
||||
this.on('error', function (err) {
|
||||
this.inStream.emit('error', err);
|
||||
});
|
||||
|
||||
this.on('end', function (err) {
|
||||
if (err) this.inStream.emit('error', err);
|
||||
this.inStream.push(null);
|
||||
});
|
||||
}
|
||||
|
||||
handleNewRows(row) {
|
||||
this.inStream.push(row);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Stream;
|
||||
249
node_modules/mariadb/lib/config/connection-options.js
generated
vendored
Normal file
249
node_modules/mariadb/lib/config/connection-options.js
generated
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
'use strict';
|
||||
|
||||
const Collations = require('../const/collations.js');
|
||||
const urlFormat = /mariadb:\/\/(([^/@:]+)?(:([^/]+))?@)?(([^/:]+)(:([0-9]+))?)\/([^?]+)(\?(.*))?$/;
|
||||
const moment = require('moment-timezone');
|
||||
const Errors = require('../misc/errors');
|
||||
|
||||
/**
|
||||
* Default option similar to mysql driver.
|
||||
* known differences
|
||||
* - no queryFormat option. Permitting client to parse is a security risk. Best is to give SQL + parameters
|
||||
* Only possible Objects are :
|
||||
* - Buffer
|
||||
* - Date
|
||||
* - Object that implement toSqlString function
|
||||
* - JSON object
|
||||
* + rowsAsArray (in mysql2) permit to have rows by index, not by name. Avoiding to parsing metadata string => faster
|
||||
*/
|
||||
class ConnectionOptions {
|
||||
constructor(opts) {
|
||||
if (typeof opts === 'string') {
|
||||
opts = ConnectionOptions.parse(opts);
|
||||
}
|
||||
|
||||
if (!opts) opts = {};
|
||||
this.bigNumberStrings = opts.bigNumberStrings || false;
|
||||
this.bulk = opts.bulk === undefined || opts.bulk;
|
||||
if (opts.charset && typeof opts.charset === 'string') {
|
||||
this.collation = Collations.fromCharset(opts.charset.toLowerCase());
|
||||
if (this.collation === undefined) {
|
||||
this.collation = Collations.fromName(opts.charset.toUpperCase());
|
||||
if (this.collation !== undefined) {
|
||||
console.log(
|
||||
"warning: please use option 'collation' " +
|
||||
"in replacement of 'charset' when using a collation name ('" +
|
||||
opts.charset +
|
||||
"')\n" +
|
||||
"(collation looks like 'UTF8MB4_UNICODE_CI', charset like 'utf8')."
|
||||
);
|
||||
}
|
||||
}
|
||||
if (this.collation === undefined)
|
||||
throw new RangeError("Unknown charset '" + opts.charset + "'");
|
||||
} else if (opts.collation && typeof opts.collation === 'string') {
|
||||
this.collation = Collations.fromName(opts.collation.toUpperCase());
|
||||
if (this.collation === undefined)
|
||||
throw new RangeError("Unknown collation '" + opts.collation + "'");
|
||||
} else {
|
||||
this.collation = Collations.fromIndex(opts.charsetNumber) || Collations.fromIndex(224); //UTF8MB4_UNICODE_CI;
|
||||
}
|
||||
this.compress = opts.compress || false;
|
||||
this.logPackets = opts.logPackets || false;
|
||||
this.connectAttributes = opts.connectAttributes || false;
|
||||
this.connectTimeout = opts.connectTimeout === undefined ? 10000 : opts.connectTimeout;
|
||||
this.queryTimeout = opts.queryTimeout === undefined ? 0 : opts.queryTimeout;
|
||||
this.socketTimeout = opts.socketTimeout === undefined ? 0 : opts.socketTimeout;
|
||||
this.database = opts.database;
|
||||
this.checkDuplicate = opts.checkDuplicate === undefined ? true : opts.checkDuplicate;
|
||||
this.dateStrings = opts.dateStrings || false;
|
||||
this.debug = opts.debug || false;
|
||||
this.debugCompress = opts.debugCompress || false;
|
||||
this.debugLen = opts.debugLen || 256;
|
||||
this.foundRows = opts.foundRows === undefined || opts.foundRows;
|
||||
this.host = opts.host || 'localhost';
|
||||
this.rsaPublicKey = opts.rsaPublicKey;
|
||||
this.cachingRsaPublicKey = opts.cachingRsaPublicKey;
|
||||
this.allowPublicKeyRetrieval = opts.allowPublicKeyRetrieval || false;
|
||||
this.initSql = opts.initSql;
|
||||
this.forceVersionCheck = opts.forceVersionCheck || false;
|
||||
this.maxAllowedPacket = opts.maxAllowedPacket;
|
||||
this.metaAsArray = opts.metaAsArray || false;
|
||||
this.multipleStatements = opts.multipleStatements || false;
|
||||
this.namedPlaceholders = opts.namedPlaceholders || false;
|
||||
this.nestTables = opts.nestTables;
|
||||
this.password = opts.password;
|
||||
this.autoJsonMap = opts.autoJsonMap === undefined ? true : opts.autoJsonMap;
|
||||
this.arrayParenthesis = opts.arrayParenthesis || false;
|
||||
this.keepAliveDelay = opts.keepAliveDelay === undefined ? 0 : opts.keepAliveDelay;
|
||||
this.permitSetMultiParamEntries = opts.permitSetMultiParamEntries || false;
|
||||
this.permitConnectionWhenExpired = opts.permitConnectionWhenExpired || false;
|
||||
this.pipelining = opts.pipelining;
|
||||
if (opts.pipelining === undefined) {
|
||||
this.permitLocalInfile = opts.permitLocalInfile || false;
|
||||
this.pipelining = !this.permitLocalInfile;
|
||||
} else {
|
||||
this.pipelining = opts.pipelining;
|
||||
if (opts.permitLocalInfile === true && this.pipelining) {
|
||||
throw new Error(
|
||||
'enabling options `permitLocalInfile` and ' +
|
||||
'`pipelining` is not possible, options are incompatible.'
|
||||
);
|
||||
}
|
||||
this.permitLocalInfile = this.pipelining ? false : opts.permitLocalInfile || false;
|
||||
}
|
||||
this.port = opts.port || 3306;
|
||||
this.rowsAsArray = opts.rowsAsArray || false;
|
||||
this.socketPath = opts.socketPath;
|
||||
this.sessionVariables = opts.sessionVariables;
|
||||
this.ssl = opts.ssl;
|
||||
if (opts.ssl) {
|
||||
if (typeof opts.ssl !== 'boolean' && typeof opts.ssl !== 'string') {
|
||||
this.ssl.rejectUnauthorized = opts.ssl.rejectUnauthorized !== false;
|
||||
}
|
||||
}
|
||||
this.supportBigNumbers = opts.supportBigNumbers || false;
|
||||
this.supportBigInt = opts.supportBigInt || false;
|
||||
this.timezone = opts.timezone || 'local';
|
||||
this.skipSetTimezone = opts.skipSetTimezone || false;
|
||||
if (this.timezone && this.timezone !== 'local' && this.timezone !== 'auto') {
|
||||
let tzName = this.timezone;
|
||||
if (this.timezone === 'Z') {
|
||||
tzName = 'Etc/UTC';
|
||||
} else {
|
||||
const matched = this.timezone.match(/([+\-\s])(\d\d):?(\d\d)?/);
|
||||
if (matched) {
|
||||
const hour = (matched[1] === '-' ? 1 : -1) * Number.parseInt(matched[2], 10);
|
||||
const minutes = matched.length > 2 && matched[3] ? Number.parseInt(matched[3], 10) : 0;
|
||||
if (minutes > 0) {
|
||||
throw new RangeError(
|
||||
"timezone format incompatible with IANA standard timezone format was '" +
|
||||
this.timezone +
|
||||
"'"
|
||||
);
|
||||
}
|
||||
if (hour == 0) {
|
||||
tzName = 'Etc/UTC';
|
||||
} else {
|
||||
tzName = 'Etc/GMT' + (matched[1] === '-' ? '+' : '') + hour;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.localTz = moment.tz.guess();
|
||||
if (tzName === this.localTz) {
|
||||
this.tz = null;
|
||||
} else {
|
||||
this.tz = tzName;
|
||||
if (!moment.tz.zone(tzName)) {
|
||||
throw Errors.createError(
|
||||
"Unknown IANA timezone '" + tzName + "'.",
|
||||
true,
|
||||
null,
|
||||
'08S01',
|
||||
Errors.ER_WRONG_IANA_TIMEZONE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.trace = opts.trace || false;
|
||||
this.typeCast = opts.typeCast;
|
||||
if (this.typeCast !== undefined && typeof this.typeCast !== 'function') {
|
||||
this.typeCast = undefined;
|
||||
}
|
||||
this.user = opts.user || process.env.USERNAME;
|
||||
|
||||
if (this.maxAllowedPacket && !Number.isInteger(this.maxAllowedPacket)) {
|
||||
throw new RangeError(
|
||||
"maxAllowedPacket must be an integer. was '" + this.maxAllowedPacket + "'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When parsing from String, correcting type.
|
||||
*
|
||||
* @param opts options
|
||||
* @return {opts}
|
||||
*/
|
||||
static parseOptionDataType(opts) {
|
||||
if (opts.bigNumberStrings) opts.bigNumberStrings = opts.bigNumberStrings == 'true';
|
||||
if (opts.bulk) opts.bulk = opts.bulk == 'true';
|
||||
if (opts.rsaPublicKey) opts.rsaPublicKey = opts.rsaPublicKey;
|
||||
if (opts.cachingRsaPublicKey) opts.cachingRsaPublicKey = opts.cachingRsaPublicKey;
|
||||
if (opts.logPackets) opts.logPackets = opts.logPackets == 'true';
|
||||
if (opts.allowPublicKeyRetrieval)
|
||||
opts.allowPublicKeyRetrieval = opts.allowPublicKeyRetrieval == 'true';
|
||||
|
||||
if (opts.charsetNumber && !isNaN(Number.parseInt(opts.charsetNumber))) {
|
||||
opts.charsetNumber = Number.parseInt(opts.charsetNumber);
|
||||
}
|
||||
if (opts.compress) opts.compress = opts.compress == 'true';
|
||||
if (opts.connectAttributes) opts.connectAttributes = JSON.parse(opts.connectAttributes);
|
||||
if (opts.connectTimeout) opts.connectTimeout = parseInt(opts.connectTimeout);
|
||||
if (opts.keepAliveDelay) opts.keepAliveDelay = parseInt(opts.keepAliveDelay);
|
||||
if (opts.socketTimeout) opts.socketTimeout = parseInt(opts.socketTimeout);
|
||||
if (opts.dateStrings) opts.dateStrings = opts.dateStrings == 'true';
|
||||
if (opts.debug) opts.debug = opts.debug == 'true';
|
||||
if (opts.autoJsonMap) opts.autoJsonMap = opts.autoJsonMap == 'true';
|
||||
if (opts.arrayParenthesis) opts.arrayParenthesis = opts.arrayParenthesis == 'true';
|
||||
if (opts.skipSetTimezone) opts.skipSetTimezone = opts.skipSetTimezone == 'true';
|
||||
|
||||
if (opts.checkDuplicate) opts.checkDuplicate = opts.checkDuplicate == 'true';
|
||||
if (opts.debugCompress) opts.debugCompress = opts.debugCompress == 'true';
|
||||
if (opts.debugLen) opts.debugLen = parseInt(opts.debugLen);
|
||||
if (opts.queryTimeout) opts.queryTimeout = parseInt(opts.queryTimeout);
|
||||
if (opts.foundRows) opts.foundRows = opts.foundRows == 'true';
|
||||
if (opts.maxAllowedPacket && !isNaN(Number.parseInt(opts.maxAllowedPacket)))
|
||||
opts.maxAllowedPacket = parseInt(opts.maxAllowedPacket);
|
||||
if (opts.metaAsArray) opts.metaAsArray = opts.metaAsArray == 'true';
|
||||
if (opts.multipleStatements) opts.multipleStatements = opts.multipleStatements == 'true';
|
||||
if (opts.namedPlaceholders) opts.namedPlaceholders = opts.namedPlaceholders == 'true';
|
||||
if (opts.nestTables) opts.nestTables = opts.nestTables == 'true';
|
||||
if (opts.permitSetMultiParamEntries)
|
||||
opts.permitSetMultiParamEntries = opts.permitSetMultiParamEntries == 'true';
|
||||
if (opts.pipelining) opts.pipelining = opts.pipelining == 'true';
|
||||
if (opts.forceVersionCheck) opts.forceVersionCheck = opts.forceVersionCheck == 'true';
|
||||
if (opts.rowsAsArray) opts.rowsAsArray = opts.rowsAsArray == 'true';
|
||||
if (opts.supportBigNumbers) opts.supportBigNumbers = opts.supportBigNumbers == 'true';
|
||||
if (opts.supportBigInt) opts.supportBigInt = opts.supportBigInt == 'true';
|
||||
if (opts.trace) opts.trace = opts.trace == 'true';
|
||||
if (opts.ssl && (opts.ssl == 'true' || opts.ssl == 'false')) opts.ssl = opts.ssl == 'true';
|
||||
return opts;
|
||||
}
|
||||
|
||||
static parse(opts) {
|
||||
const matchResults = opts.match(urlFormat);
|
||||
|
||||
if (!matchResults) {
|
||||
throw new Error(
|
||||
"error parsing connection string '" +
|
||||
opts +
|
||||
"'. format must be 'mariadb://[<user>[:<password>]@]<host>[:<port>]/[<db>[?<opt1>=<value1>[&<opt2>=<value2>]]]'"
|
||||
);
|
||||
}
|
||||
const options = {
|
||||
user: matchResults[2] ? decodeURIComponent(matchResults[2]) : undefined,
|
||||
password: matchResults[4] ? decodeURIComponent(matchResults[4]) : undefined,
|
||||
host: matchResults[6] ? decodeURIComponent(matchResults[6]) : matchResults[6],
|
||||
port: matchResults[8] ? parseInt(matchResults[8]) : undefined,
|
||||
database: matchResults[9] ? decodeURIComponent(matchResults[9]) : matchResults[9]
|
||||
};
|
||||
|
||||
const variousOptsString = matchResults[11];
|
||||
if (variousOptsString) {
|
||||
const keyVals = variousOptsString.split('&');
|
||||
keyVals.forEach(function (keyVal) {
|
||||
const equalIdx = keyVal.indexOf('=');
|
||||
if (equalIdx !== 1) {
|
||||
let val = keyVal.substring(equalIdx + 1);
|
||||
val = val ? decodeURIComponent(val) : undefined;
|
||||
options[keyVal.substring(0, equalIdx)] = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return this.parseOptionDataType(options);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ConnectionOptions;
|
||||
19
node_modules/mariadb/lib/config/pool-cluster-options.js
generated
vendored
Normal file
19
node_modules/mariadb/lib/config/pool-cluster-options.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
class PoolClusterOptions {
|
||||
constructor(opts) {
|
||||
if (opts) {
|
||||
this.canRetry = opts.canRetry === undefined ? true : opts.canRetry;
|
||||
this.removeNodeErrorCount = opts.removeNodeErrorCount || 5;
|
||||
this.restoreNodeTimeout = opts.restoreNodeTimeout || 1000;
|
||||
this.defaultSelector = opts.defaultSelector || 'RR';
|
||||
} else {
|
||||
this.canRetry = true;
|
||||
this.removeNodeErrorCount = 5;
|
||||
this.restoreNodeTimeout = 1000;
|
||||
this.defaultSelector = 'RR';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PoolClusterOptions;
|
||||
47
node_modules/mariadb/lib/config/pool-options.js
generated
vendored
Normal file
47
node_modules/mariadb/lib/config/pool-options.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
let ConnOptions = require('./connection-options');
|
||||
|
||||
class PoolOptions {
|
||||
constructor(opts) {
|
||||
if (typeof opts === 'string') {
|
||||
opts = ConnOptions.parse(opts);
|
||||
|
||||
//set data type
|
||||
if (opts.acquireTimeout) opts.acquireTimeout = parseInt(opts.acquireTimeout);
|
||||
if (opts.connectionLimit) opts.connectionLimit = parseInt(opts.connectionLimit);
|
||||
if (opts.idleTimeout) opts.idleTimeout = parseInt(opts.idleTimeout);
|
||||
if (opts.leakDetectionTimeout)
|
||||
opts.leakDetectionTimeout = parseInt(opts.leakDetectionTimeout);
|
||||
if (opts.initializationTimeout)
|
||||
opts.initializationTimeout = parseInt(opts.initializationTimeout);
|
||||
if (opts.minDelayValidation) opts.minDelayValidation = parseInt(opts.minDelayValidation);
|
||||
if (opts.minimumIdle) opts.minimumIdle = parseInt(opts.minimumIdle);
|
||||
if (opts.noControlAfterUse) opts.noControlAfterUse = opts.noControlAfterUse == 'true';
|
||||
if (opts.resetAfterUse) opts.resetAfterUse = opts.resetAfterUse == 'true';
|
||||
if (opts.pingTimeout) opts.pingTimeout = parseInt(opts.pingTimeout);
|
||||
}
|
||||
|
||||
this.acquireTimeout = opts.acquireTimeout === undefined ? 10000 : opts.acquireTimeout;
|
||||
this.connectionLimit = opts.connectionLimit === undefined ? 10 : opts.connectionLimit;
|
||||
this.idleTimeout = opts.idleTimeout || 1800;
|
||||
this.leakDetectionTimeout = opts.leakDetectionTimeout || 0;
|
||||
this.initializationTimeout =
|
||||
opts.initializationTimeout === undefined ? 30000 : opts.initializationTimeout;
|
||||
this.minDelayValidation = opts.minDelayValidation === undefined ? 500 : opts.minDelayValidation;
|
||||
this.minimumIdle =
|
||||
opts.minimumIdle === undefined
|
||||
? this.connectionLimit
|
||||
: Math.min(opts.minimumIdle, this.connectionLimit);
|
||||
this.noControlAfterUse = opts.noControlAfterUse || false;
|
||||
this.resetAfterUse = opts.resetAfterUse === undefined ? true : opts.resetAfterUse;
|
||||
this.pingTimeout = opts.pingTimeout || 250;
|
||||
this.connOptions = new ConnOptions(opts);
|
||||
|
||||
if (this.acquireTimeout > 0 && this.connOptions.connectTimeout > this.acquireTimeout) {
|
||||
this.connOptions.connectTimeout = this.acquireTimeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PoolOptions;
|
||||
158
node_modules/mariadb/lib/connection-callback.js
generated
vendored
Normal file
158
node_modules/mariadb/lib/connection-callback.js
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
'use strict';
|
||||
|
||||
const Connection = require('./connection');
|
||||
const util = require('util');
|
||||
const Errors = require('./misc/errors');
|
||||
const { Status } = require('./const/connection_status');
|
||||
|
||||
function ConnectionCallback(options) {
|
||||
Connection.call(this, options);
|
||||
|
||||
let connecting = 1;
|
||||
const connectPromise = this.connect.bind(this);
|
||||
const changeUserPromise = this.changeUser.bind(this);
|
||||
const queryPromise = this.query.bind(this);
|
||||
const endPromise = this.end.bind(this);
|
||||
const pingPromise = this.ping.bind(this);
|
||||
const resetPromise = this.reset.bind(this);
|
||||
const commitPromise = this.commit.bind(this);
|
||||
const rollbackPromise = this.rollback.bind(this);
|
||||
|
||||
const emptySuccess = (rows) => {};
|
||||
const emptyError = (err) => {};
|
||||
|
||||
//*****************************************************************
|
||||
// internal equivalent with callback of promised functions
|
||||
//*****************************************************************
|
||||
|
||||
const _commitCallback = (callback) => {
|
||||
commitPromise()
|
||||
.then(() => {
|
||||
if (callback) callback(null, null, null);
|
||||
})
|
||||
.catch(callback || emptyError);
|
||||
};
|
||||
|
||||
const _rollbackCallback = (callback) => {
|
||||
rollbackPromise()
|
||||
.then(() => {
|
||||
if (callback) callback(null, null, null);
|
||||
})
|
||||
.catch(callback || emptyError);
|
||||
};
|
||||
|
||||
const _pingCallback = (timeout, callback) => {
|
||||
let _timeout, _cb;
|
||||
if (typeof timeout === 'function') {
|
||||
_cb = timeout;
|
||||
_timeout = undefined;
|
||||
} else {
|
||||
_timeout = timeout;
|
||||
_cb = callback;
|
||||
}
|
||||
pingPromise(_timeout)
|
||||
.then(_cb || emptySuccess)
|
||||
.catch(_cb || emptyError);
|
||||
};
|
||||
|
||||
const _resetCallback = (callback) => {
|
||||
resetPromise()
|
||||
.then(callback || emptySuccess)
|
||||
.catch(callback || emptyError);
|
||||
};
|
||||
|
||||
const _beginTransactionCallback = (callback) => {
|
||||
queryPromise('START TRANSACTION')
|
||||
.then(() => {
|
||||
if (callback) callback(null, null, null);
|
||||
})
|
||||
.catch(callback || emptyError);
|
||||
};
|
||||
|
||||
const _endCallback = (callback) => {
|
||||
endPromise()
|
||||
.then(callback || emptySuccess)
|
||||
.catch(callback || emptyError);
|
||||
};
|
||||
|
||||
const _connectCallback = function (callback) {
|
||||
if (!callback) {
|
||||
throw new Errors.createError(
|
||||
'missing callback parameter',
|
||||
false,
|
||||
this.info,
|
||||
'HY000',
|
||||
Errors.ER_MISSING_PARAMETER
|
||||
);
|
||||
}
|
||||
|
||||
if (connecting === 1) {
|
||||
this.on('connect', callback);
|
||||
} else {
|
||||
switch (this._status()) {
|
||||
case Status.CLOSING:
|
||||
case Status.CLOSED:
|
||||
callback(
|
||||
Errors.createError(
|
||||
'Connection closed',
|
||||
true,
|
||||
this.info,
|
||||
'08S01',
|
||||
Errors.ER_CONNECTION_ALREADY_CLOSED
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _changeUserCallback = (options, callback) => {
|
||||
let _options, _cb;
|
||||
if (typeof options === 'function') {
|
||||
_cb = options;
|
||||
_options = undefined;
|
||||
} else {
|
||||
_options = options;
|
||||
_cb = callback;
|
||||
}
|
||||
|
||||
changeUserPromise(_options)
|
||||
.then(() => {
|
||||
if (_cb) _cb(null, null, null);
|
||||
})
|
||||
.catch(_cb || emptyError);
|
||||
};
|
||||
|
||||
//*****************************************************************
|
||||
// replacing public promise function with callback equivalent
|
||||
//*****************************************************************
|
||||
|
||||
this.commit = _commitCallback;
|
||||
this.rollback = _rollbackCallback;
|
||||
this.ping = _pingCallback;
|
||||
this.reset = _resetCallback;
|
||||
this.end = _endCallback;
|
||||
this.connect = _connectCallback;
|
||||
this.changeUser = _changeUserCallback;
|
||||
this.query = this._queryCallback;
|
||||
this.batch = this._batchCallback;
|
||||
this.beginTransaction = _beginTransactionCallback;
|
||||
|
||||
const self = this;
|
||||
connectPromise()
|
||||
.then(() => {
|
||||
connecting = 0;
|
||||
self.emit('connect');
|
||||
})
|
||||
.catch((err) => {
|
||||
connecting = 0;
|
||||
self.emit('connect', err);
|
||||
});
|
||||
}
|
||||
|
||||
util.inherits(ConnectionCallback, Connection);
|
||||
|
||||
module.exports = ConnectionCallback;
|
||||
1435
node_modules/mariadb/lib/connection.js
generated
vendored
Normal file
1435
node_modules/mariadb/lib/connection.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
64
node_modules/mariadb/lib/const/capabilities.js
generated
vendored
Normal file
64
node_modules/mariadb/lib/const/capabilities.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Capabilities list ( with 'CLIENT_' removed)
|
||||
* see : https://mariadb.com/kb/en/library/1-connecting-connecting/#capabilities
|
||||
*/
|
||||
/* mysql/old mariadb server/client */
|
||||
module.exports.MYSQL = BigInt(1);
|
||||
/* Found instead of affected rows */
|
||||
module.exports.FOUND_ROWS = BigInt(2);
|
||||
/* get all column flags */
|
||||
module.exports.LONG_FLAG = BigInt(4);
|
||||
/* one can specify db on connect */
|
||||
module.exports.CONNECT_WITH_DB = BigInt(8);
|
||||
/* don't allow database.table.column */
|
||||
module.exports.NO_SCHEMA = BigInt(1) << BigInt(4);
|
||||
/* can use compression protocol */
|
||||
module.exports.COMPRESS = BigInt(1) << BigInt(5);
|
||||
/* odbc client */
|
||||
module.exports.ODBC = BigInt(1) << BigInt(6);
|
||||
/* can use LOAD DATA LOCAL */
|
||||
module.exports.LOCAL_FILES = BigInt(1) << BigInt(7);
|
||||
/* ignore spaces before '' */
|
||||
module.exports.IGNORE_SPACE = BigInt(1) << BigInt(8);
|
||||
/* new 4.1 protocol */
|
||||
module.exports.PROTOCOL_41 = BigInt(1) << BigInt(9);
|
||||
/* this is an interactive client */
|
||||
module.exports.INTERACTIVE = BigInt(1) << BigInt(10);
|
||||
/* switch to ssl after handshake */
|
||||
module.exports.SSL = BigInt(1) << BigInt(11);
|
||||
/* IGNORE sigpipes */
|
||||
module.exports.IGNORE_SIGPIPE = BigInt(1) << BigInt(12);
|
||||
/* client knows about transactions */
|
||||
module.exports.TRANSACTIONS = BigInt(1) << BigInt(13);
|
||||
/* old flag for 4.1 protocol */
|
||||
module.exports.RESERVED = BigInt(1) << BigInt(14);
|
||||
/* new 4.1 authentication */
|
||||
module.exports.SECURE_CONNECTION = BigInt(1) << BigInt(15);
|
||||
/* enable/disable multi-stmt support */
|
||||
module.exports.MULTI_STATEMENTS = BigInt(1) << BigInt(16);
|
||||
/* enable/disable multi-results */
|
||||
module.exports.MULTI_RESULTS = BigInt(1) << BigInt(17);
|
||||
/* multi-results in ps-protocol */
|
||||
module.exports.PS_MULTI_RESULTS = BigInt(1) << BigInt(18);
|
||||
/* client supports plugin authentication */
|
||||
module.exports.PLUGIN_AUTH = BigInt(1) << BigInt(19);
|
||||
/* permits connection attributes */
|
||||
module.exports.CONNECT_ATTRS = BigInt(1) << BigInt(20);
|
||||
/* Enable authentication response packet to be larger than 255 bytes. */
|
||||
module.exports.PLUGIN_AUTH_LENENC_CLIENT_DATA = BigInt(1) << BigInt(21);
|
||||
/* Don't close the connection for a connection with expired password. */
|
||||
module.exports.CAN_HANDLE_EXPIRED_PASSWORDS = BigInt(1) << BigInt(22);
|
||||
/* Capable of handling server state change information. Its a hint to the
|
||||
server to include the state change information in Ok packet. */
|
||||
module.exports.SESSION_TRACK = BigInt(1) << BigInt(23);
|
||||
/* Client no longer needs EOF packet */
|
||||
module.exports.DEPRECATE_EOF = BigInt(1) << BigInt(24);
|
||||
module.exports.SSL_VERIFY_SERVER_CERT = BigInt(1) << BigInt(30);
|
||||
|
||||
/* MariaDB extended capabilities */
|
||||
|
||||
/* Permit bulk insert*/
|
||||
module.exports.MARIADB_CLIENT_STMT_BULK_OPERATIONS = BigInt(1) << BigInt(34);
|
||||
|
||||
/* Clients supporting extended metadata */
|
||||
module.exports.MARIADB_CLIENT_EXTENDED_TYPE_INFO = BigInt(1) << BigInt(35);
|
||||
473
node_modules/mariadb/lib/const/collations.js
generated
vendored
Normal file
473
node_modules/mariadb/lib/const/collations.js
generated
vendored
Normal file
@@ -0,0 +1,473 @@
|
||||
'use strict';
|
||||
|
||||
let charsets = [];
|
||||
let defaultCharsets = [];
|
||||
|
||||
class Collation {
|
||||
constructor(index, name, charset, maxLength) {
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
static fromCharset(charset) {
|
||||
return defaultCharsets[charset];
|
||||
}
|
||||
|
||||
static fromIndex(index) {
|
||||
if (index >= charsets.length) return undefined;
|
||||
return charsets[index];
|
||||
}
|
||||
|
||||
static fromName(name) {
|
||||
for (let i = 0; i < charsets.length; i++) {
|
||||
let collation = charsets[i];
|
||||
if (collation && collation.name === name) {
|
||||
return collation;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// generated with query :
|
||||
// SELECT CONCAT('charsets[', CAST(co.ID as char), '] = new Collation(', CAST(co.ID as char), ', \'',
|
||||
// UPPER(co.COLLATION_NAME), '\', \'', co.CHARACTER_SET_NAME, '\', ', CAST(ca.MAXLEN as char), ');\n')
|
||||
// FROM information_schema.COLLATIONS co
|
||||
// LEFT OUTER JOIN information_schema.CHARACTER_SETS ca ON ca.character_set_name = co.character_set_name
|
||||
// ORDER BY co.ID ASC;
|
||||
//then replace "utf8mb4" by "utf8"
|
||||
|
||||
charsets[1] = new Collation(1, 'BIG5_CHINESE_CI', 'big5', 2);
|
||||
charsets[2] = new Collation(2, 'LATIN2_CZECH_CS', 'latin2', 1);
|
||||
charsets[3] = new Collation(3, 'DEC8_SWEDISH_CI', 'dec8', 1);
|
||||
charsets[4] = new Collation(4, 'CP850_GENERAL_CI', 'cp850', 1);
|
||||
charsets[5] = new Collation(5, 'LATIN1_GERMAN1_CI', 'latin1', 1);
|
||||
charsets[6] = new Collation(6, 'HP8_ENGLISH_CI', 'hp8', 1);
|
||||
charsets[7] = new Collation(7, 'KOI8R_GENERAL_CI', 'koi8r', 1);
|
||||
charsets[8] = new Collation(8, 'LATIN1_SWEDISH_CI', 'latin1', 1);
|
||||
charsets[9] = new Collation(9, 'LATIN2_GENERAL_CI', 'latin2', 1);
|
||||
charsets[10] = new Collation(10, 'SWE7_SWEDISH_CI', 'swe7', 1);
|
||||
charsets[11] = new Collation(11, 'ASCII_GENERAL_CI', 'ascii', 1);
|
||||
charsets[12] = new Collation(12, 'UJIS_JAPANESE_CI', 'ujis', 3);
|
||||
charsets[13] = new Collation(13, 'SJIS_JAPANESE_CI', 'sjis', 2);
|
||||
charsets[14] = new Collation(14, 'CP1251_BULGARIAN_CI', 'cp1251', 1);
|
||||
charsets[15] = new Collation(15, 'LATIN1_DANISH_CI', 'latin1', 1);
|
||||
charsets[16] = new Collation(16, 'HEBREW_GENERAL_CI', 'hebrew', 1);
|
||||
charsets[18] = new Collation(18, 'TIS620_THAI_CI', 'tis620', 1);
|
||||
charsets[19] = new Collation(19, 'EUCKR_KOREAN_CI', 'euckr', 2);
|
||||
charsets[20] = new Collation(20, 'LATIN7_ESTONIAN_CS', 'latin7', 1);
|
||||
charsets[21] = new Collation(21, 'LATIN2_HUNGARIAN_CI', 'latin2', 1);
|
||||
charsets[22] = new Collation(22, 'KOI8U_GENERAL_CI', 'koi8u', 1);
|
||||
charsets[23] = new Collation(23, 'CP1251_UKRAINIAN_CI', 'cp1251', 1);
|
||||
charsets[24] = new Collation(24, 'GB2312_CHINESE_CI', 'gb2312', 2);
|
||||
charsets[25] = new Collation(25, 'GREEK_GENERAL_CI', 'greek', 1);
|
||||
charsets[26] = new Collation(26, 'CP1250_GENERAL_CI', 'cp1250', 1);
|
||||
charsets[27] = new Collation(27, 'LATIN2_CROATIAN_CI', 'latin2', 1);
|
||||
charsets[28] = new Collation(28, 'GBK_CHINESE_CI', 'gbk', 2);
|
||||
charsets[29] = new Collation(29, 'CP1257_LITHUANIAN_CI', 'cp1257', 1);
|
||||
charsets[30] = new Collation(30, 'LATIN5_TURKISH_CI', 'latin5', 1);
|
||||
charsets[31] = new Collation(31, 'LATIN1_GERMAN2_CI', 'latin1', 1);
|
||||
charsets[32] = new Collation(32, 'ARMSCII8_GENERAL_CI', 'armscii8', 1);
|
||||
charsets[33] = new Collation(33, 'UTF8_GENERAL_CI', 'utf8', 3);
|
||||
charsets[34] = new Collation(34, 'CP1250_CZECH_CS', 'cp1250', 1);
|
||||
charsets[35] = new Collation(35, 'UCS2_GENERAL_CI', 'ucs2', 2);
|
||||
charsets[36] = new Collation(36, 'CP866_GENERAL_CI', 'cp866', 1);
|
||||
charsets[37] = new Collation(37, 'KEYBCS2_GENERAL_CI', 'keybcs2', 1);
|
||||
charsets[38] = new Collation(38, 'MACCE_GENERAL_CI', 'macce', 1);
|
||||
charsets[39] = new Collation(39, 'MACROMAN_GENERAL_CI', 'macroman', 1);
|
||||
charsets[40] = new Collation(40, 'CP852_GENERAL_CI', 'cp852', 1);
|
||||
charsets[41] = new Collation(41, 'LATIN7_GENERAL_CI', 'latin7', 1);
|
||||
charsets[42] = new Collation(42, 'LATIN7_GENERAL_CS', 'latin7', 1);
|
||||
charsets[43] = new Collation(43, 'MACCE_BIN', 'macce', 1);
|
||||
charsets[44] = new Collation(44, 'CP1250_CROATIAN_CI', 'cp1250', 1);
|
||||
charsets[45] = new Collation(45, 'UTF8MB4_GENERAL_CI', 'utf8', 4);
|
||||
charsets[46] = new Collation(46, 'UTF8MB4_BIN', 'utf8', 4);
|
||||
charsets[47] = new Collation(47, 'LATIN1_BIN', 'latin1', 1);
|
||||
charsets[48] = new Collation(48, 'LATIN1_GENERAL_CI', 'latin1', 1);
|
||||
charsets[49] = new Collation(49, 'LATIN1_GENERAL_CS', 'latin1', 1);
|
||||
charsets[50] = new Collation(50, 'CP1251_BIN', 'cp1251', 1);
|
||||
charsets[51] = new Collation(51, 'CP1251_GENERAL_CI', 'cp1251', 1);
|
||||
charsets[52] = new Collation(52, 'CP1251_GENERAL_CS', 'cp1251', 1);
|
||||
charsets[53] = new Collation(53, 'MACROMAN_BIN', 'macroman', 1);
|
||||
charsets[54] = new Collation(54, 'UTF16_GENERAL_CI', 'utf16', 4);
|
||||
charsets[55] = new Collation(55, 'UTF16_BIN', 'utf16', 4);
|
||||
charsets[56] = new Collation(56, 'UTF16LE_GENERAL_CI', 'utf16le', 4);
|
||||
charsets[57] = new Collation(57, 'CP1256_GENERAL_CI', 'cp1256', 1);
|
||||
charsets[58] = new Collation(58, 'CP1257_BIN', 'cp1257', 1);
|
||||
charsets[59] = new Collation(59, 'CP1257_GENERAL_CI', 'cp1257', 1);
|
||||
charsets[60] = new Collation(60, 'UTF32_GENERAL_CI', 'utf32', 4);
|
||||
charsets[61] = new Collation(61, 'UTF32_BIN', 'utf32', 4);
|
||||
charsets[62] = new Collation(62, 'UTF16LE_BIN', 'utf16le', 4);
|
||||
charsets[63] = new Collation(63, 'BINARY', 'binary', 1);
|
||||
charsets[64] = new Collation(64, 'ARMSCII8_BIN', 'armscii8', 1);
|
||||
charsets[65] = new Collation(65, 'ASCII_BIN', 'ascii', 1);
|
||||
charsets[66] = new Collation(66, 'CP1250_BIN', 'cp1250', 1);
|
||||
charsets[67] = new Collation(67, 'CP1256_BIN', 'cp1256', 1);
|
||||
charsets[68] = new Collation(68, 'CP866_BIN', 'cp866', 1);
|
||||
charsets[69] = new Collation(69, 'DEC8_BIN', 'dec8', 1);
|
||||
charsets[70] = new Collation(70, 'GREEK_BIN', 'greek', 1);
|
||||
charsets[71] = new Collation(71, 'HEBREW_BIN', 'hebrew', 1);
|
||||
charsets[72] = new Collation(72, 'HP8_BIN', 'hp8', 1);
|
||||
charsets[73] = new Collation(73, 'KEYBCS2_BIN', 'keybcs2', 1);
|
||||
charsets[74] = new Collation(74, 'KOI8R_BIN', 'koi8r', 1);
|
||||
charsets[75] = new Collation(75, 'KOI8U_BIN', 'koi8u', 1);
|
||||
charsets[76] = new Collation(76, 'UTF8_TOLOWER_CI', 'utf8', 3);
|
||||
charsets[77] = new Collation(77, 'LATIN2_BIN', 'latin2', 1);
|
||||
charsets[78] = new Collation(78, 'LATIN5_BIN', 'latin5', 1);
|
||||
charsets[79] = new Collation(79, 'LATIN7_BIN', 'latin7', 1);
|
||||
charsets[80] = new Collation(80, 'CP850_BIN', 'cp850', 1);
|
||||
charsets[81] = new Collation(81, 'CP852_BIN', 'cp852', 1);
|
||||
charsets[82] = new Collation(82, 'SWE7_BIN', 'swe7', 1);
|
||||
charsets[83] = new Collation(83, 'UTF8_BIN', 'utf8', 3);
|
||||
charsets[84] = new Collation(84, 'BIG5_BIN', 'big5', 2);
|
||||
charsets[85] = new Collation(85, 'EUCKR_BIN', 'euckr', 2);
|
||||
charsets[86] = new Collation(86, 'GB2312_BIN', 'gb2312', 2);
|
||||
charsets[87] = new Collation(87, 'GBK_BIN', 'gbk', 2);
|
||||
charsets[88] = new Collation(88, 'SJIS_BIN', 'sjis', 2);
|
||||
charsets[89] = new Collation(89, 'TIS620_BIN', 'tis620', 1);
|
||||
charsets[90] = new Collation(90, 'UCS2_BIN', 'ucs2', 2);
|
||||
charsets[91] = new Collation(91, 'UJIS_BIN', 'ujis', 3);
|
||||
charsets[92] = new Collation(92, 'GEOSTD8_GENERAL_CI', 'geostd8', 1);
|
||||
charsets[93] = new Collation(93, 'GEOSTD8_BIN', 'geostd8', 1);
|
||||
charsets[94] = new Collation(94, 'LATIN1_SPANISH_CI', 'latin1', 1);
|
||||
charsets[95] = new Collation(95, 'CP932_JAPANESE_CI', 'cp932', 2);
|
||||
charsets[96] = new Collation(96, 'CP932_BIN', 'cp932', 2);
|
||||
charsets[97] = new Collation(97, 'EUCJPMS_JAPANESE_CI', 'eucjpms', 3);
|
||||
charsets[98] = new Collation(98, 'EUCJPMS_BIN', 'eucjpms', 3);
|
||||
charsets[99] = new Collation(99, 'CP1250_POLISH_CI', 'cp1250', 1);
|
||||
charsets[101] = new Collation(101, 'UTF16_UNICODE_CI', 'utf16', 4);
|
||||
charsets[102] = new Collation(102, 'UTF16_ICELANDIC_CI', 'utf16', 4);
|
||||
charsets[103] = new Collation(103, 'UTF16_LATVIAN_CI', 'utf16', 4);
|
||||
charsets[104] = new Collation(104, 'UTF16_ROMANIAN_CI', 'utf16', 4);
|
||||
charsets[105] = new Collation(105, 'UTF16_SLOVENIAN_CI', 'utf16', 4);
|
||||
charsets[106] = new Collation(106, 'UTF16_POLISH_CI', 'utf16', 4);
|
||||
charsets[107] = new Collation(107, 'UTF16_ESTONIAN_CI', 'utf16', 4);
|
||||
charsets[108] = new Collation(108, 'UTF16_SPANISH_CI', 'utf16', 4);
|
||||
charsets[109] = new Collation(109, 'UTF16_SWEDISH_CI', 'utf16', 4);
|
||||
charsets[110] = new Collation(110, 'UTF16_TURKISH_CI', 'utf16', 4);
|
||||
charsets[111] = new Collation(111, 'UTF16_CZECH_CI', 'utf16', 4);
|
||||
charsets[112] = new Collation(112, 'UTF16_DANISH_CI', 'utf16', 4);
|
||||
charsets[113] = new Collation(113, 'UTF16_LITHUANIAN_CI', 'utf16', 4);
|
||||
charsets[114] = new Collation(114, 'UTF16_SLOVAK_CI', 'utf16', 4);
|
||||
charsets[115] = new Collation(115, 'UTF16_SPANISH2_CI', 'utf16', 4);
|
||||
charsets[116] = new Collation(116, 'UTF16_ROMAN_CI', 'utf16', 4);
|
||||
charsets[117] = new Collation(117, 'UTF16_PERSIAN_CI', 'utf16', 4);
|
||||
charsets[118] = new Collation(118, 'UTF16_ESPERANTO_CI', 'utf16', 4);
|
||||
charsets[119] = new Collation(119, 'UTF16_HUNGARIAN_CI', 'utf16', 4);
|
||||
charsets[120] = new Collation(120, 'UTF16_SINHALA_CI', 'utf16', 4);
|
||||
charsets[121] = new Collation(121, 'UTF16_GERMAN2_CI', 'utf16', 4);
|
||||
charsets[122] = new Collation(122, 'UTF16_CROATIAN_MYSQL561_CI', 'utf16', 4);
|
||||
charsets[123] = new Collation(123, 'UTF16_UNICODE_520_CI', 'utf16', 4);
|
||||
charsets[124] = new Collation(124, 'UTF16_VIETNAMESE_CI', 'utf16', 4);
|
||||
charsets[128] = new Collation(128, 'UCS2_UNICODE_CI', 'ucs2', 2);
|
||||
charsets[129] = new Collation(129, 'UCS2_ICELANDIC_CI', 'ucs2', 2);
|
||||
charsets[130] = new Collation(130, 'UCS2_LATVIAN_CI', 'ucs2', 2);
|
||||
charsets[131] = new Collation(131, 'UCS2_ROMANIAN_CI', 'ucs2', 2);
|
||||
charsets[132] = new Collation(132, 'UCS2_SLOVENIAN_CI', 'ucs2', 2);
|
||||
charsets[133] = new Collation(133, 'UCS2_POLISH_CI', 'ucs2', 2);
|
||||
charsets[134] = new Collation(134, 'UCS2_ESTONIAN_CI', 'ucs2', 2);
|
||||
charsets[135] = new Collation(135, 'UCS2_SPANISH_CI', 'ucs2', 2);
|
||||
charsets[136] = new Collation(136, 'UCS2_SWEDISH_CI', 'ucs2', 2);
|
||||
charsets[137] = new Collation(137, 'UCS2_TURKISH_CI', 'ucs2', 2);
|
||||
charsets[138] = new Collation(138, 'UCS2_CZECH_CI', 'ucs2', 2);
|
||||
charsets[139] = new Collation(139, 'UCS2_DANISH_CI', 'ucs2', 2);
|
||||
charsets[140] = new Collation(140, 'UCS2_LITHUANIAN_CI', 'ucs2', 2);
|
||||
charsets[141] = new Collation(141, 'UCS2_SLOVAK_CI', 'ucs2', 2);
|
||||
charsets[142] = new Collation(142, 'UCS2_SPANISH2_CI', 'ucs2', 2);
|
||||
charsets[143] = new Collation(143, 'UCS2_ROMAN_CI', 'ucs2', 2);
|
||||
charsets[144] = new Collation(144, 'UCS2_PERSIAN_CI', 'ucs2', 2);
|
||||
charsets[145] = new Collation(145, 'UCS2_ESPERANTO_CI', 'ucs2', 2);
|
||||
charsets[146] = new Collation(146, 'UCS2_HUNGARIAN_CI', 'ucs2', 2);
|
||||
charsets[147] = new Collation(147, 'UCS2_SINHALA_CI', 'ucs2', 2);
|
||||
charsets[148] = new Collation(148, 'UCS2_GERMAN2_CI', 'ucs2', 2);
|
||||
charsets[149] = new Collation(149, 'UCS2_CROATIAN_MYSQL561_CI', 'ucs2', 2);
|
||||
charsets[150] = new Collation(150, 'UCS2_UNICODE_520_CI', 'ucs2', 2);
|
||||
charsets[151] = new Collation(151, 'UCS2_VIETNAMESE_CI', 'ucs2', 2);
|
||||
charsets[159] = new Collation(159, 'UCS2_GENERAL_MYSQL500_CI', 'ucs2', 2);
|
||||
charsets[160] = new Collation(160, 'UTF32_UNICODE_CI', 'utf32', 4);
|
||||
charsets[161] = new Collation(161, 'UTF32_ICELANDIC_CI', 'utf32', 4);
|
||||
charsets[162] = new Collation(162, 'UTF32_LATVIAN_CI', 'utf32', 4);
|
||||
charsets[163] = new Collation(163, 'UTF32_ROMANIAN_CI', 'utf32', 4);
|
||||
charsets[164] = new Collation(164, 'UTF32_SLOVENIAN_CI', 'utf32', 4);
|
||||
charsets[165] = new Collation(165, 'UTF32_POLISH_CI', 'utf32', 4);
|
||||
charsets[166] = new Collation(166, 'UTF32_ESTONIAN_CI', 'utf32', 4);
|
||||
charsets[167] = new Collation(167, 'UTF32_SPANISH_CI', 'utf32', 4);
|
||||
charsets[168] = new Collation(168, 'UTF32_SWEDISH_CI', 'utf32', 4);
|
||||
charsets[169] = new Collation(169, 'UTF32_TURKISH_CI', 'utf32', 4);
|
||||
charsets[170] = new Collation(170, 'UTF32_CZECH_CI', 'utf32', 4);
|
||||
charsets[171] = new Collation(171, 'UTF32_DANISH_CI', 'utf32', 4);
|
||||
charsets[172] = new Collation(172, 'UTF32_LITHUANIAN_CI', 'utf32', 4);
|
||||
charsets[173] = new Collation(173, 'UTF32_SLOVAK_CI', 'utf32', 4);
|
||||
charsets[174] = new Collation(174, 'UTF32_SPANISH2_CI', 'utf32', 4);
|
||||
charsets[175] = new Collation(175, 'UTF32_ROMAN_CI', 'utf32', 4);
|
||||
charsets[176] = new Collation(176, 'UTF32_PERSIAN_CI', 'utf32', 4);
|
||||
charsets[177] = new Collation(177, 'UTF32_ESPERANTO_CI', 'utf32', 4);
|
||||
charsets[178] = new Collation(178, 'UTF32_HUNGARIAN_CI', 'utf32', 4);
|
||||
charsets[179] = new Collation(179, 'UTF32_SINHALA_CI', 'utf32', 4);
|
||||
charsets[180] = new Collation(180, 'UTF32_GERMAN2_CI', 'utf32', 4);
|
||||
charsets[181] = new Collation(181, 'UTF32_CROATIAN_MYSQL561_CI', 'utf32', 4);
|
||||
charsets[182] = new Collation(182, 'UTF32_UNICODE_520_CI', 'utf32', 4);
|
||||
charsets[183] = new Collation(183, 'UTF32_VIETNAMESE_CI', 'utf32', 4);
|
||||
charsets[192] = new Collation(192, 'UTF8_UNICODE_CI', 'utf8', 3);
|
||||
charsets[193] = new Collation(193, 'UTF8_ICELANDIC_CI', 'utf8', 3);
|
||||
charsets[194] = new Collation(194, 'UTF8_LATVIAN_CI', 'utf8', 3);
|
||||
charsets[195] = new Collation(195, 'UTF8_ROMANIAN_CI', 'utf8', 3);
|
||||
charsets[196] = new Collation(196, 'UTF8_SLOVENIAN_CI', 'utf8', 3);
|
||||
charsets[197] = new Collation(197, 'UTF8_POLISH_CI', 'utf8', 3);
|
||||
charsets[198] = new Collation(198, 'UTF8_ESTONIAN_CI', 'utf8', 3);
|
||||
charsets[199] = new Collation(199, 'UTF8_SPANISH_CI', 'utf8', 3);
|
||||
charsets[200] = new Collation(200, 'UTF8_SWEDISH_CI', 'utf8', 3);
|
||||
charsets[201] = new Collation(201, 'UTF8_TURKISH_CI', 'utf8', 3);
|
||||
charsets[202] = new Collation(202, 'UTF8_CZECH_CI', 'utf8', 3);
|
||||
charsets[203] = new Collation(203, 'UTF8_DANISH_CI', 'utf8', 3);
|
||||
charsets[204] = new Collation(204, 'UTF8_LITHUANIAN_CI', 'utf8', 3);
|
||||
charsets[205] = new Collation(205, 'UTF8_SLOVAK_CI', 'utf8', 3);
|
||||
charsets[206] = new Collation(206, 'UTF8_SPANISH2_CI', 'utf8', 3);
|
||||
charsets[207] = new Collation(207, 'UTF8_ROMAN_CI', 'utf8', 3);
|
||||
charsets[208] = new Collation(208, 'UTF8_PERSIAN_CI', 'utf8', 3);
|
||||
charsets[209] = new Collation(209, 'UTF8_ESPERANTO_CI', 'utf8', 3);
|
||||
charsets[210] = new Collation(210, 'UTF8_HUNGARIAN_CI', 'utf8', 3);
|
||||
charsets[211] = new Collation(211, 'UTF8_SINHALA_CI', 'utf8', 3);
|
||||
charsets[212] = new Collation(212, 'UTF8_GERMAN2_CI', 'utf8', 3);
|
||||
charsets[213] = new Collation(213, 'UTF8_CROATIAN_MYSQL561_CI', 'utf8', 3);
|
||||
charsets[214] = new Collation(214, 'UTF8_UNICODE_520_CI', 'utf8', 3);
|
||||
charsets[215] = new Collation(215, 'UTF8_VIETNAMESE_CI', 'utf8', 3);
|
||||
charsets[223] = new Collation(223, 'UTF8_GENERAL_MYSQL500_CI', 'utf8', 3);
|
||||
charsets[224] = new Collation(224, 'UTF8MB4_UNICODE_CI', 'utf8', 4);
|
||||
charsets[225] = new Collation(225, 'UTF8MB4_ICELANDIC_CI', 'utf8', 4);
|
||||
charsets[226] = new Collation(226, 'UTF8MB4_LATVIAN_CI', 'utf8', 4);
|
||||
charsets[227] = new Collation(227, 'UTF8MB4_ROMANIAN_CI', 'utf8', 4);
|
||||
charsets[228] = new Collation(228, 'UTF8MB4_SLOVENIAN_CI', 'utf8', 4);
|
||||
charsets[229] = new Collation(229, 'UTF8MB4_POLISH_CI', 'utf8', 4);
|
||||
charsets[230] = new Collation(230, 'UTF8MB4_ESTONIAN_CI', 'utf8', 4);
|
||||
charsets[231] = new Collation(231, 'UTF8MB4_SPANISH_CI', 'utf8', 4);
|
||||
charsets[232] = new Collation(232, 'UTF8MB4_SWEDISH_CI', 'utf8', 4);
|
||||
charsets[233] = new Collation(233, 'UTF8MB4_TURKISH_CI', 'utf8', 4);
|
||||
charsets[234] = new Collation(234, 'UTF8MB4_CZECH_CI', 'utf8', 4);
|
||||
charsets[235] = new Collation(235, 'UTF8MB4_DANISH_CI', 'utf8', 4);
|
||||
charsets[236] = new Collation(236, 'UTF8MB4_LITHUANIAN_CI', 'utf8', 4);
|
||||
charsets[237] = new Collation(237, 'UTF8MB4_SLOVAK_CI', 'utf8', 4);
|
||||
charsets[238] = new Collation(238, 'UTF8MB4_SPANISH2_CI', 'utf8', 4);
|
||||
charsets[239] = new Collation(239, 'UTF8MB4_ROMAN_CI', 'utf8', 4);
|
||||
charsets[240] = new Collation(240, 'UTF8MB4_PERSIAN_CI', 'utf8', 4);
|
||||
charsets[241] = new Collation(241, 'UTF8MB4_ESPERANTO_CI', 'utf8', 4);
|
||||
charsets[242] = new Collation(242, 'UTF8MB4_HUNGARIAN_CI', 'utf8', 4);
|
||||
charsets[243] = new Collation(243, 'UTF8MB4_SINHALA_CI', 'utf8', 4);
|
||||
charsets[244] = new Collation(244, 'UTF8MB4_GERMAN2_CI', 'utf8', 4);
|
||||
charsets[245] = new Collation(245, 'UTF8MB4_CROATIAN_MYSQL561_CI', 'utf8', 4);
|
||||
charsets[246] = new Collation(246, 'UTF8MB4_UNICODE_520_CI', 'utf8', 4);
|
||||
charsets[247] = new Collation(247, 'UTF8MB4_VIETNAMESE_CI', 'utf8', 4);
|
||||
charsets[248] = new Collation(248, 'GB18030_CHINESE_CI', 'gb18030', 4);
|
||||
charsets[249] = new Collation(249, 'GB18030_BIN', 'gb18030', 4);
|
||||
charsets[250] = new Collation(250, 'GB18030_UNICODE_520_CI', 'gb18030', 4);
|
||||
charsets[255] = new Collation(255, 'UTF8MB4_0900_AI_CI', 'utf8', 4);
|
||||
charsets[256] = new Collation(256, 'UTF8MB4_DE_PB_0900_AI_CI', 'utf8', 4);
|
||||
charsets[257] = new Collation(257, 'UTF8MB4_IS_0900_AI_CI', 'utf8', 4);
|
||||
charsets[258] = new Collation(258, 'UTF8MB4_LV_0900_AI_CI', 'utf8', 4);
|
||||
charsets[259] = new Collation(259, 'UTF8MB4_RO_0900_AI_CI', 'utf8', 4);
|
||||
charsets[260] = new Collation(260, 'UTF8MB4_SL_0900_AI_CI', 'utf8', 4);
|
||||
charsets[261] = new Collation(261, 'UTF8MB4_PL_0900_AI_CI', 'utf8', 4);
|
||||
charsets[262] = new Collation(262, 'UTF8MB4_ET_0900_AI_CI', 'utf8', 4);
|
||||
charsets[263] = new Collation(263, 'UTF8MB4_ES_0900_AI_CI', 'utf8', 4);
|
||||
charsets[264] = new Collation(264, 'UTF8MB4_SV_0900_AI_CI', 'utf8', 4);
|
||||
charsets[265] = new Collation(265, 'UTF8MB4_TR_0900_AI_CI', 'utf8', 4);
|
||||
charsets[266] = new Collation(266, 'UTF8MB4_CS_0900_AI_CI', 'utf8', 4);
|
||||
charsets[267] = new Collation(267, 'UTF8MB4_DA_0900_AI_CI', 'utf8', 4);
|
||||
charsets[268] = new Collation(268, 'UTF8MB4_LT_0900_AI_CI', 'utf8', 4);
|
||||
charsets[269] = new Collation(269, 'UTF8MB4_SK_0900_AI_CI', 'utf8', 4);
|
||||
charsets[270] = new Collation(270, 'UTF8MB4_ES_TRAD_0900_AI_CI', 'utf8', 4);
|
||||
charsets[271] = new Collation(271, 'UTF8MB4_LA_0900_AI_CI', 'utf8', 4);
|
||||
charsets[273] = new Collation(273, 'UTF8MB4_EO_0900_AI_CI', 'utf8', 4);
|
||||
charsets[274] = new Collation(274, 'UTF8MB4_HU_0900_AI_CI', 'utf8', 4);
|
||||
charsets[275] = new Collation(275, 'UTF8MB4_HR_0900_AI_CI', 'utf8', 4);
|
||||
charsets[277] = new Collation(277, 'UTF8MB4_VI_0900_AI_CI', 'utf8', 4);
|
||||
charsets[278] = new Collation(278, 'UTF8MB4_0900_AS_CS', 'utf8', 4);
|
||||
charsets[279] = new Collation(279, 'UTF8MB4_DE_PB_0900_AS_CS', 'utf8', 4);
|
||||
charsets[280] = new Collation(280, 'UTF8MB4_IS_0900_AS_CS', 'utf8', 4);
|
||||
charsets[281] = new Collation(281, 'UTF8MB4_LV_0900_AS_CS', 'utf8', 4);
|
||||
charsets[282] = new Collation(282, 'UTF8MB4_RO_0900_AS_CS', 'utf8', 4);
|
||||
charsets[283] = new Collation(283, 'UTF8MB4_SL_0900_AS_CS', 'utf8', 4);
|
||||
charsets[284] = new Collation(284, 'UTF8MB4_PL_0900_AS_CS', 'utf8', 4);
|
||||
charsets[285] = new Collation(285, 'UTF8MB4_ET_0900_AS_CS', 'utf8', 4);
|
||||
charsets[286] = new Collation(286, 'UTF8MB4_ES_0900_AS_CS', 'utf8', 4);
|
||||
charsets[287] = new Collation(287, 'UTF8MB4_SV_0900_AS_CS', 'utf8', 4);
|
||||
charsets[288] = new Collation(288, 'UTF8MB4_TR_0900_AS_CS', 'utf8', 4);
|
||||
charsets[289] = new Collation(289, 'UTF8MB4_CS_0900_AS_CS', 'utf8', 4);
|
||||
charsets[290] = new Collation(290, 'UTF8MB4_DA_0900_AS_CS', 'utf8', 4);
|
||||
charsets[291] = new Collation(291, 'UTF8MB4_LT_0900_AS_CS', 'utf8', 4);
|
||||
charsets[292] = new Collation(292, 'UTF8MB4_SK_0900_AS_CS', 'utf8', 4);
|
||||
charsets[293] = new Collation(293, 'UTF8MB4_ES_TRAD_0900_AS_CS', 'utf8', 4);
|
||||
charsets[294] = new Collation(294, 'UTF8MB4_LA_0900_AS_CS', 'utf8', 4);
|
||||
charsets[296] = new Collation(296, 'UTF8MB4_EO_0900_AS_CS', 'utf8', 4);
|
||||
charsets[297] = new Collation(297, 'UTF8MB4_HU_0900_AS_CS', 'utf8', 4);
|
||||
charsets[298] = new Collation(298, 'UTF8MB4_HR_0900_AS_CS', 'utf8', 4);
|
||||
charsets[300] = new Collation(300, 'UTF8MB4_VI_0900_AS_CS', 'utf8', 4);
|
||||
charsets[303] = new Collation(303, 'UTF8MB4_JA_0900_AS_CS', 'utf8', 4);
|
||||
charsets[304] = new Collation(304, 'UTF8MB4_JA_0900_AS_CS_KS', 'utf8', 4);
|
||||
charsets[305] = new Collation(305, 'UTF8MB4_0900_AS_CI', 'utf8', 4);
|
||||
charsets[306] = new Collation(306, 'UTF8MB4_RU_0900_AI_CI', 'utf8', 4);
|
||||
charsets[307] = new Collation(307, 'UTF8MB4_RU_0900_AS_CS', 'utf8', 4);
|
||||
charsets[308] = new Collation(308, 'UTF8MB4_ZH_0900_AS_CS', 'utf8', 4);
|
||||
charsets[309] = new Collation(309, 'UTF8MB4_0900_BIN', 'utf8', 4);
|
||||
charsets[576] = new Collation(576, 'UTF8_CROATIAN_CI', 'utf8', 3);
|
||||
charsets[577] = new Collation(577, 'UTF8_MYANMAR_CI', 'utf8', 3);
|
||||
charsets[578] = new Collation(578, 'UTF8_THAI_520_W2', 'utf8', 3);
|
||||
charsets[608] = new Collation(608, 'UTF8MB4_CROATIAN_CI', 'utf8', 4);
|
||||
charsets[609] = new Collation(609, 'UTF8MB4_MYANMAR_CI', 'utf8', 4);
|
||||
charsets[610] = new Collation(610, 'UTF8MB4_THAI_520_W2', 'utf8', 4);
|
||||
charsets[640] = new Collation(640, 'UCS2_CROATIAN_CI', 'ucs2', 2);
|
||||
charsets[641] = new Collation(641, 'UCS2_MYANMAR_CI', 'ucs2', 2);
|
||||
charsets[642] = new Collation(642, 'UCS2_THAI_520_W2', 'ucs2', 2);
|
||||
charsets[672] = new Collation(672, 'UTF16_CROATIAN_CI', 'utf16', 4);
|
||||
charsets[673] = new Collation(673, 'UTF16_MYANMAR_CI', 'utf16', 4);
|
||||
charsets[674] = new Collation(674, 'UTF16_THAI_520_W2', 'utf16', 4);
|
||||
charsets[736] = new Collation(736, 'UTF32_CROATIAN_CI', 'utf32', 4);
|
||||
charsets[737] = new Collation(737, 'UTF32_MYANMAR_CI', 'utf32', 4);
|
||||
charsets[738] = new Collation(738, 'UTF32_THAI_520_W2', 'utf32', 4);
|
||||
charsets[1025] = new Collation(1025, 'BIG5_CHINESE_NOPAD_CI', 'big5', 2);
|
||||
charsets[1027] = new Collation(1027, 'DEC8_SWEDISH_NOPAD_CI', 'dec8', 1);
|
||||
charsets[1028] = new Collation(1028, 'CP850_GENERAL_NOPAD_CI', 'cp850', 1);
|
||||
charsets[1030] = new Collation(1030, 'HP8_ENGLISH_NOPAD_CI', 'hp8', 1);
|
||||
charsets[1031] = new Collation(1031, 'KOI8R_GENERAL_NOPAD_CI', 'koi8r', 1);
|
||||
charsets[1032] = new Collation(1032, 'LATIN1_SWEDISH_NOPAD_CI', 'latin1', 1);
|
||||
charsets[1033] = new Collation(1033, 'LATIN2_GENERAL_NOPAD_CI', 'latin2', 1);
|
||||
charsets[1034] = new Collation(1034, 'SWE7_SWEDISH_NOPAD_CI', 'swe7', 1);
|
||||
charsets[1035] = new Collation(1035, 'ASCII_GENERAL_NOPAD_CI', 'ascii', 1);
|
||||
charsets[1036] = new Collation(1036, 'UJIS_JAPANESE_NOPAD_CI', 'ujis', 3);
|
||||
charsets[1037] = new Collation(1037, 'SJIS_JAPANESE_NOPAD_CI', 'sjis', 2);
|
||||
charsets[1040] = new Collation(1040, 'HEBREW_GENERAL_NOPAD_CI', 'hebrew', 1);
|
||||
charsets[1042] = new Collation(1042, 'TIS620_THAI_NOPAD_CI', 'tis620', 1);
|
||||
charsets[1043] = new Collation(1043, 'EUCKR_KOREAN_NOPAD_CI', 'euckr', 2);
|
||||
charsets[1046] = new Collation(1046, 'KOI8U_GENERAL_NOPAD_CI', 'koi8u', 1);
|
||||
charsets[1048] = new Collation(1048, 'GB2312_CHINESE_NOPAD_CI', 'gb2312', 2);
|
||||
charsets[1049] = new Collation(1049, 'GREEK_GENERAL_NOPAD_CI', 'greek', 1);
|
||||
charsets[1050] = new Collation(1050, 'CP1250_GENERAL_NOPAD_CI', 'cp1250', 1);
|
||||
charsets[1052] = new Collation(1052, 'GBK_CHINESE_NOPAD_CI', 'gbk', 2);
|
||||
charsets[1054] = new Collation(1054, 'LATIN5_TURKISH_NOPAD_CI', 'latin5', 1);
|
||||
charsets[1056] = new Collation(1056, 'ARMSCII8_GENERAL_NOPAD_CI', 'armscii8', 1);
|
||||
charsets[1057] = new Collation(1057, 'UTF8_GENERAL_NOPAD_CI', 'utf8', 3);
|
||||
charsets[1059] = new Collation(1059, 'UCS2_GENERAL_NOPAD_CI', 'ucs2', 2);
|
||||
charsets[1060] = new Collation(1060, 'CP866_GENERAL_NOPAD_CI', 'cp866', 1);
|
||||
charsets[1061] = new Collation(1061, 'KEYBCS2_GENERAL_NOPAD_CI', 'keybcs2', 1);
|
||||
charsets[1062] = new Collation(1062, 'MACCE_GENERAL_NOPAD_CI', 'macce', 1);
|
||||
charsets[1063] = new Collation(1063, 'MACROMAN_GENERAL_NOPAD_CI', 'macroman', 1);
|
||||
charsets[1064] = new Collation(1064, 'CP852_GENERAL_NOPAD_CI', 'cp852', 1);
|
||||
charsets[1065] = new Collation(1065, 'LATIN7_GENERAL_NOPAD_CI', 'latin7', 1);
|
||||
charsets[1067] = new Collation(1067, 'MACCE_NOPAD_BIN', 'macce', 1);
|
||||
charsets[1069] = new Collation(1069, 'UTF8MB4_GENERAL_NOPAD_CI', 'utf8', 4);
|
||||
charsets[1070] = new Collation(1070, 'UTF8MB4_NOPAD_BIN', 'utf8', 4);
|
||||
charsets[1071] = new Collation(1071, 'LATIN1_NOPAD_BIN', 'latin1', 1);
|
||||
charsets[1074] = new Collation(1074, 'CP1251_NOPAD_BIN', 'cp1251', 1);
|
||||
charsets[1075] = new Collation(1075, 'CP1251_GENERAL_NOPAD_CI', 'cp1251', 1);
|
||||
charsets[1077] = new Collation(1077, 'MACROMAN_NOPAD_BIN', 'macroman', 1);
|
||||
charsets[1078] = new Collation(1078, 'UTF16_GENERAL_NOPAD_CI', 'utf16', 4);
|
||||
charsets[1079] = new Collation(1079, 'UTF16_NOPAD_BIN', 'utf16', 4);
|
||||
charsets[1080] = new Collation(1080, 'UTF16LE_GENERAL_NOPAD_CI', 'utf16le', 4);
|
||||
charsets[1081] = new Collation(1081, 'CP1256_GENERAL_NOPAD_CI', 'cp1256', 1);
|
||||
charsets[1082] = new Collation(1082, 'CP1257_NOPAD_BIN', 'cp1257', 1);
|
||||
charsets[1083] = new Collation(1083, 'CP1257_GENERAL_NOPAD_CI', 'cp1257', 1);
|
||||
charsets[1084] = new Collation(1084, 'UTF32_GENERAL_NOPAD_CI', 'utf32', 4);
|
||||
charsets[1085] = new Collation(1085, 'UTF32_NOPAD_BIN', 'utf32', 4);
|
||||
charsets[1086] = new Collation(1086, 'UTF16LE_NOPAD_BIN', 'utf16le', 4);
|
||||
charsets[1088] = new Collation(1088, 'ARMSCII8_NOPAD_BIN', 'armscii8', 1);
|
||||
charsets[1089] = new Collation(1089, 'ASCII_NOPAD_BIN', 'ascii', 1);
|
||||
charsets[1090] = new Collation(1090, 'CP1250_NOPAD_BIN', 'cp1250', 1);
|
||||
charsets[1091] = new Collation(1091, 'CP1256_NOPAD_BIN', 'cp1256', 1);
|
||||
charsets[1092] = new Collation(1092, 'CP866_NOPAD_BIN', 'cp866', 1);
|
||||
charsets[1093] = new Collation(1093, 'DEC8_NOPAD_BIN', 'dec8', 1);
|
||||
charsets[1094] = new Collation(1094, 'GREEK_NOPAD_BIN', 'greek', 1);
|
||||
charsets[1095] = new Collation(1095, 'HEBREW_NOPAD_BIN', 'hebrew', 1);
|
||||
charsets[1096] = new Collation(1096, 'HP8_NOPAD_BIN', 'hp8', 1);
|
||||
charsets[1097] = new Collation(1097, 'KEYBCS2_NOPAD_BIN', 'keybcs2', 1);
|
||||
charsets[1098] = new Collation(1098, 'KOI8R_NOPAD_BIN', 'koi8r', 1);
|
||||
charsets[1099] = new Collation(1099, 'KOI8U_NOPAD_BIN', 'koi8u', 1);
|
||||
charsets[1101] = new Collation(1101, 'LATIN2_NOPAD_BIN', 'latin2', 1);
|
||||
charsets[1102] = new Collation(1102, 'LATIN5_NOPAD_BIN', 'latin5', 1);
|
||||
charsets[1103] = new Collation(1103, 'LATIN7_NOPAD_BIN', 'latin7', 1);
|
||||
charsets[1104] = new Collation(1104, 'CP850_NOPAD_BIN', 'cp850', 1);
|
||||
charsets[1105] = new Collation(1105, 'CP852_NOPAD_BIN', 'cp852', 1);
|
||||
charsets[1106] = new Collation(1106, 'SWE7_NOPAD_BIN', 'swe7', 1);
|
||||
charsets[1107] = new Collation(1107, 'UTF8_NOPAD_BIN', 'utf8', 3);
|
||||
charsets[1108] = new Collation(1108, 'BIG5_NOPAD_BIN', 'big5', 2);
|
||||
charsets[1109] = new Collation(1109, 'EUCKR_NOPAD_BIN', 'euckr', 2);
|
||||
charsets[1110] = new Collation(1110, 'GB2312_NOPAD_BIN', 'gb2312', 2);
|
||||
charsets[1111] = new Collation(1111, 'GBK_NOPAD_BIN', 'gbk', 2);
|
||||
charsets[1112] = new Collation(1112, 'SJIS_NOPAD_BIN', 'sjis', 2);
|
||||
charsets[1113] = new Collation(1113, 'TIS620_NOPAD_BIN', 'tis620', 1);
|
||||
charsets[1114] = new Collation(1114, 'UCS2_NOPAD_BIN', 'ucs2', 2);
|
||||
charsets[1115] = new Collation(1115, 'UJIS_NOPAD_BIN', 'ujis', 3);
|
||||
charsets[1116] = new Collation(1116, 'GEOSTD8_GENERAL_NOPAD_CI', 'geostd8', 1);
|
||||
charsets[1117] = new Collation(1117, 'GEOSTD8_NOPAD_BIN', 'geostd8', 1);
|
||||
charsets[1119] = new Collation(1119, 'CP932_JAPANESE_NOPAD_CI', 'cp932', 2);
|
||||
charsets[1120] = new Collation(1120, 'CP932_NOPAD_BIN', 'cp932', 2);
|
||||
charsets[1121] = new Collation(1121, 'EUCJPMS_JAPANESE_NOPAD_CI', 'eucjpms', 3);
|
||||
charsets[1122] = new Collation(1122, 'EUCJPMS_NOPAD_BIN', 'eucjpms', 3);
|
||||
charsets[1125] = new Collation(1125, 'UTF16_UNICODE_NOPAD_CI', 'utf16', 4);
|
||||
charsets[1147] = new Collation(1147, 'UTF16_UNICODE_520_NOPAD_CI', 'utf16', 4);
|
||||
charsets[1152] = new Collation(1152, 'UCS2_UNICODE_NOPAD_CI', 'ucs2', 2);
|
||||
charsets[1174] = new Collation(1174, 'UCS2_UNICODE_520_NOPAD_CI', 'ucs2', 2);
|
||||
charsets[1184] = new Collation(1184, 'UTF32_UNICODE_NOPAD_CI', 'utf32', 4);
|
||||
charsets[1206] = new Collation(1206, 'UTF32_UNICODE_520_NOPAD_CI', 'utf32', 4);
|
||||
charsets[1216] = new Collation(1216, 'UTF8_UNICODE_NOPAD_CI', 'utf8', 3);
|
||||
charsets[1238] = new Collation(1238, 'UTF8_UNICODE_520_NOPAD_CI', 'utf8', 3);
|
||||
charsets[1248] = new Collation(1248, 'UTF8MB4_UNICODE_NOPAD_CI', 'utf8', 4);
|
||||
charsets[1270] = new Collation(1270, 'UTF8MB4_UNICODE_520_NOPAD_CI', 'utf8', 4);
|
||||
|
||||
for (let i = 0; i < charsets.length; i++) {
|
||||
let collation = charsets[i];
|
||||
if (collation) {
|
||||
Collation.prototype[collation.name] = collation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map charset to default collation
|
||||
*
|
||||
* created with query:
|
||||
* SELECT CONCAT(' defaultCharsets[\'', co.character_set_name , '\'] = charsets[', CAST(co.ID as char), '];')
|
||||
* FROM information_schema.COLLATIONS co WHERE co.IS_DEFAULT = 'Yes' ORDER BY co.ID ASC;
|
||||
*/
|
||||
defaultCharsets['big5'] = charsets[1];
|
||||
defaultCharsets['dec8'] = charsets[3];
|
||||
defaultCharsets['cp850'] = charsets[4];
|
||||
defaultCharsets['hp8'] = charsets[6];
|
||||
defaultCharsets['koi8r'] = charsets[7];
|
||||
defaultCharsets['latin1'] = charsets[8];
|
||||
defaultCharsets['latin2'] = charsets[9];
|
||||
defaultCharsets['swe7'] = charsets[10];
|
||||
defaultCharsets['ascii'] = charsets[11];
|
||||
defaultCharsets['ujis'] = charsets[12];
|
||||
defaultCharsets['sjis'] = charsets[13];
|
||||
defaultCharsets['hebrew'] = charsets[16];
|
||||
defaultCharsets['tis620'] = charsets[18];
|
||||
defaultCharsets['euckr'] = charsets[19];
|
||||
defaultCharsets['koi8u'] = charsets[22];
|
||||
defaultCharsets['gb2312'] = charsets[24];
|
||||
defaultCharsets['greek'] = charsets[25];
|
||||
defaultCharsets['cp1250'] = charsets[26];
|
||||
defaultCharsets['gbk'] = charsets[28];
|
||||
defaultCharsets['latin5'] = charsets[30];
|
||||
defaultCharsets['armscii8'] = charsets[32];
|
||||
defaultCharsets['utf8'] = charsets[33];
|
||||
defaultCharsets['ucs2'] = charsets[35];
|
||||
defaultCharsets['cp866'] = charsets[36];
|
||||
defaultCharsets['keybcs2'] = charsets[37];
|
||||
defaultCharsets['macce'] = charsets[38];
|
||||
defaultCharsets['macroman'] = charsets[39];
|
||||
defaultCharsets['cp852'] = charsets[40];
|
||||
defaultCharsets['latin7'] = charsets[41];
|
||||
defaultCharsets['utf8mb4'] = charsets[45];
|
||||
defaultCharsets['cp1251'] = charsets[51];
|
||||
defaultCharsets['utf16'] = charsets[54];
|
||||
defaultCharsets['utf16le'] = charsets[56];
|
||||
defaultCharsets['cp1256'] = charsets[57];
|
||||
defaultCharsets['cp1257'] = charsets[59];
|
||||
defaultCharsets['utf32'] = charsets[60];
|
||||
defaultCharsets['binary'] = charsets[63];
|
||||
defaultCharsets['geostd8'] = charsets[92];
|
||||
defaultCharsets['cp932'] = charsets[95];
|
||||
defaultCharsets['eucjpms'] = charsets[97];
|
||||
defaultCharsets['gb18030'] = charsets[248];
|
||||
|
||||
module.exports = Collation;
|
||||
13
node_modules/mariadb/lib/const/connection_status.js
generated
vendored
Normal file
13
node_modules/mariadb/lib/const/connection_status.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const Status = {
|
||||
NOT_CONNECTED: 1,
|
||||
CONNECTING: 2,
|
||||
AUTHENTICATING: 3,
|
||||
INIT_CMD: 4,
|
||||
CONNECTED: 5,
|
||||
CLOSING: 6,
|
||||
CLOSED: 7
|
||||
};
|
||||
|
||||
module.exports.Status = Status;
|
||||
1282
node_modules/mariadb/lib/const/error-code.js
generated
vendored
Normal file
1282
node_modules/mariadb/lib/const/error-code.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
35
node_modules/mariadb/lib/const/field-detail.js
generated
vendored
Normal file
35
node_modules/mariadb/lib/const/field-detail.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Column definition packet "Field detail" flag value
|
||||
* see : https://mariadb.com/kb/en/library/resultset/#field-detail-flag
|
||||
*/
|
||||
|
||||
// field cannot be null
|
||||
module.exports.NOT_NULL = 1;
|
||||
// field is a primary key
|
||||
module.exports.PRIMARY_KEY = 2;
|
||||
//field is unique
|
||||
module.exports.UNIQUE_KEY = 4;
|
||||
//field is in a multiple key
|
||||
module.exports.MULTIPLE_KEY = 8;
|
||||
//is this field a Blob
|
||||
module.exports.BLOB = 1 << 4;
|
||||
// is this field unsigned
|
||||
module.exports.UNSIGNED = 1 << 5;
|
||||
//is this field a zerofill
|
||||
module.exports.ZEROFILL_FLAG = 1 << 6;
|
||||
//whether this field has a binary collation
|
||||
module.exports.BINARY_COLLATION = 1 << 7;
|
||||
//Field is an enumeration
|
||||
module.exports.ENUM = 1 << 8;
|
||||
//field auto-increment
|
||||
module.exports.AUTO_INCREMENT = 1 << 9;
|
||||
//field is a timestamp value
|
||||
module.exports.TIMESTAMP = 1 << 10;
|
||||
//field is a SET
|
||||
module.exports.SET = 1 << 11;
|
||||
//field doesn't have default value
|
||||
module.exports.NO_DEFAULT_VALUE_FLAG = 1 << 12;
|
||||
//field is set to NOW on UPDATE
|
||||
module.exports.ON_UPDATE_NOW_FLAG = 1 << 13;
|
||||
//field is num
|
||||
module.exports.NUM_FLAG = 1 << 14;
|
||||
71
node_modules/mariadb/lib/const/field-type.js
generated
vendored
Normal file
71
node_modules/mariadb/lib/const/field-type.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Field types
|
||||
* see https://mariadb.com/kb/en/library/resultset/#field-types
|
||||
*/
|
||||
|
||||
module.exports.DECIMAL = 0;
|
||||
module.exports.TINY = 1;
|
||||
module.exports.SHORT = 2;
|
||||
module.exports.LONG = 3;
|
||||
module.exports.FLOAT = 4;
|
||||
module.exports.DOUBLE = 5;
|
||||
module.exports.NULL = 6;
|
||||
module.exports.TIMESTAMP = 7;
|
||||
module.exports.LONGLONG = 8;
|
||||
module.exports.INT24 = 9;
|
||||
module.exports.DATE = 10;
|
||||
module.exports.TIME = 11;
|
||||
module.exports.DATETIME = 12;
|
||||
module.exports.YEAR = 13;
|
||||
module.exports.NEWDATE = 14;
|
||||
module.exports.VARCHAR = 15;
|
||||
module.exports.BIT = 16;
|
||||
module.exports.TIMESTAMP2 = 17;
|
||||
module.exports.DATETIME2 = 18;
|
||||
module.exports.TIME2 = 19;
|
||||
module.exports.JSON = 245; //only for MySQL
|
||||
module.exports.NEWDECIMAL = 246;
|
||||
module.exports.ENUM = 247;
|
||||
module.exports.SET = 248;
|
||||
module.exports.TINY_BLOB = 249;
|
||||
module.exports.MEDIUM_BLOB = 250;
|
||||
module.exports.LONG_BLOB = 251;
|
||||
module.exports.BLOB = 252;
|
||||
module.exports.VAR_STRING = 253;
|
||||
module.exports.STRING = 254;
|
||||
module.exports.GEOMETRY = 255;
|
||||
|
||||
const typeNames = [];
|
||||
typeNames[0] = 'DECIMAL';
|
||||
typeNames[1] = 'TINY';
|
||||
typeNames[2] = 'SHORT';
|
||||
typeNames[3] = 'LONG';
|
||||
typeNames[4] = 'FLOAT';
|
||||
typeNames[5] = 'DOUBLE';
|
||||
typeNames[6] = 'NULL';
|
||||
typeNames[7] = 'TIMESTAMP';
|
||||
typeNames[8] = 'LONGLONG';
|
||||
typeNames[9] = 'INT24';
|
||||
typeNames[10] = 'DATE';
|
||||
typeNames[11] = 'TIME';
|
||||
typeNames[12] = 'DATETIME';
|
||||
typeNames[13] = 'YEAR';
|
||||
typeNames[14] = 'NEWDATE';
|
||||
typeNames[15] = 'VARCHAR';
|
||||
typeNames[16] = 'BIT';
|
||||
typeNames[17] = 'TIMESTAMP2';
|
||||
typeNames[18] = 'DATETIME2';
|
||||
typeNames[19] = 'TIME2';
|
||||
typeNames[245] = 'JSON';
|
||||
typeNames[246] = 'NEWDECIMAL';
|
||||
typeNames[247] = 'ENUM';
|
||||
typeNames[248] = 'SET';
|
||||
typeNames[249] = 'TINY_BLOB';
|
||||
typeNames[250] = 'MEDIUM_BLOB';
|
||||
typeNames[251] = 'LONG_BLOB';
|
||||
typeNames[252] = 'BLOB';
|
||||
typeNames[253] = 'VAR_STRING';
|
||||
typeNames[254] = 'STRING';
|
||||
typeNames[255] = 'GEOMETRY';
|
||||
|
||||
module.exports.TYPES = typeNames;
|
||||
30
node_modules/mariadb/lib/const/server-status.js
generated
vendored
Normal file
30
node_modules/mariadb/lib/const/server-status.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* possible server status flag value
|
||||
* see https://mariadb.com/kb/en/library/ok_packet/#server-status-flag
|
||||
* @type {number}
|
||||
*/
|
||||
//A transaction is currently active
|
||||
module.exports.STATUS_IN_TRANS = 1;
|
||||
//Autocommit mode is set
|
||||
module.exports.STATUS_AUTOCOMMIT = 2;
|
||||
//more results exists (more packet follow)
|
||||
module.exports.MORE_RESULTS_EXISTS = 8;
|
||||
module.exports.QUERY_NO_GOOD_INDEX_USED = 16;
|
||||
module.exports.QUERY_NO_INDEX_USED = 32;
|
||||
//when using COM_STMT_FETCH, indicate that current cursor still has result (deprecated)
|
||||
module.exports.STATUS_CURSOR_EXISTS = 64;
|
||||
//when using COM_STMT_FETCH, indicate that current cursor has finished to send results (deprecated)
|
||||
module.exports.STATUS_LAST_ROW_SENT = 128;
|
||||
//database has been dropped
|
||||
module.exports.STATUS_DB_DROPPED = 1 << 8;
|
||||
//current escape mode is "no backslash escape"
|
||||
module.exports.STATUS_NO_BACKSLASH_ESCAPES = 1 << 9;
|
||||
//A DDL change did have an impact on an existing PREPARE (an automatic reprepare has been executed)
|
||||
module.exports.STATUS_METADATA_CHANGED = 1 << 10;
|
||||
module.exports.QUERY_WAS_SLOW = 1 << 11;
|
||||
//this result-set contain stored procedure output parameter
|
||||
module.exports.PS_OUT_PARAMS = 1 << 12;
|
||||
//current transaction is a read-only transaction
|
||||
module.exports.STATUS_IN_TRANS_READONLY = 1 << 13;
|
||||
//session state change. see Session change type for more information
|
||||
module.exports.SESSION_STATE_CHANGED = 1 << 14;
|
||||
12
node_modules/mariadb/lib/const/state-change.js
generated
vendored
Normal file
12
node_modules/mariadb/lib/const/state-change.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Session change type.
|
||||
* see : https://mariadb.com/kb/en/library/ok_packet/#session-change-type
|
||||
* @type {number}
|
||||
*/
|
||||
|
||||
module.exports.SESSION_TRACK_SYSTEM_VARIABLES = 0;
|
||||
module.exports.SESSION_TRACK_SCHEMA = 1;
|
||||
module.exports.SESSION_TRACK_STATE_CHANGE = 2;
|
||||
module.exports.SESSION_TRACK_GTIDS = 3;
|
||||
module.exports.SESSION_TRACK_TRANSACTION_CHARACTERISTICS = 4;
|
||||
module.exports.SESSION_TRACK_TRANSACTION_STATE = 5;
|
||||
81
node_modules/mariadb/lib/filtered-pool-cluster.js
generated
vendored
Normal file
81
node_modules/mariadb/lib/filtered-pool-cluster.js
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Similar to pool cluster with pre-set pattern and selector.
|
||||
* Additional method query
|
||||
*
|
||||
* @param poolCluster cluster
|
||||
* @param patternArg pre-set pattern
|
||||
* @param selectorArg pre-set selector
|
||||
* @constructor
|
||||
*/
|
||||
function FilteredPoolCluster(poolCluster, patternArg, selectorArg) {
|
||||
const cluster = poolCluster;
|
||||
const pattern = patternArg;
|
||||
const selector = selectorArg;
|
||||
|
||||
/**
|
||||
* Get a connection according to previously indicated pattern and selector.
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.getConnection = () => {
|
||||
return cluster.getConnection(pattern, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a query on one connection from available pools matching pattern
|
||||
* in cluster.
|
||||
*
|
||||
* @param sql sql command
|
||||
* @param value parameter value of sql command (not mandatory)
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.query = function (sql, value) {
|
||||
return cluster
|
||||
.getConnection(pattern, selector)
|
||||
.then((conn) => {
|
||||
return conn
|
||||
.query(sql, value)
|
||||
.then((res) => {
|
||||
conn.end();
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
conn.end();
|
||||
return Promise.reject(err);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a batch on one connection from available pools matching pattern
|
||||
* in cluster.
|
||||
*
|
||||
* @param sql sql command
|
||||
* @param value parameter value of sql command
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.batch = function (sql, value) {
|
||||
return cluster
|
||||
.getConnection(pattern, selector)
|
||||
.then((conn) => {
|
||||
return conn
|
||||
.batch(sql, value)
|
||||
.then((res) => {
|
||||
conn.end();
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
conn.end();
|
||||
return Promise.reject(err);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = FilteredPoolCluster;
|
||||
590
node_modules/mariadb/lib/io/bulk-packet.js
generated
vendored
Normal file
590
node_modules/mariadb/lib/io/bulk-packet.js
generated
vendored
Normal file
@@ -0,0 +1,590 @@
|
||||
'use strict';
|
||||
|
||||
const moment = require('moment-timezone');
|
||||
const Iconv = require('iconv-lite');
|
||||
const SMALL_BUFFER_SIZE = 1024;
|
||||
const MEDIUM_BUFFER_SIZE = 16384; //16k
|
||||
const LARGE_BUFFER_SIZE = 131072; //128k
|
||||
const BIG_BUFFER_SIZE = 1048576; //1M
|
||||
const MAX_BUFFER_SIZE = 16777219; //16M + 4
|
||||
|
||||
/**
|
||||
* Packet splitter.
|
||||
*
|
||||
* The servers have a limit max_allowed_packet which limits the size of the data sent, to avoid saturating the server in memory.
|
||||
*
|
||||
* The following implementation has a workaround that will rewrite the command and separate the send according to this value.
|
||||
* This implies that this command can send multiple commands, with some tricks for sequencing packets.
|
||||
*
|
||||
*/
|
||||
class BulkPacket {
|
||||
constructor(opts, out, row) {
|
||||
this.out = out;
|
||||
this.buf = Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
this.pos = 4;
|
||||
this.datatypes = [];
|
||||
this.encoding = out.encoding;
|
||||
this.statementId = -1;
|
||||
this.waitingResponseNo = 1;
|
||||
this.singleQuery = false;
|
||||
this.haveErrorResponse = false;
|
||||
this.writeBinaryDate = opts.tz
|
||||
? opts.tz === 'Etc/UTC'
|
||||
? this.writeBinaryUtcDate
|
||||
: this.writeBinaryTimezoneDate
|
||||
: this.writeBinaryLocalDate;
|
||||
if (this.encoding === 'utf8') {
|
||||
this.writeLengthEncodedString = this.writeDefaultLengthEncodedString;
|
||||
} else if (Buffer.isEncoding(this.encoding)) {
|
||||
this.writeLengthEncodedString = this.writeDefaultLengthEncodedString;
|
||||
} else {
|
||||
this.writeLengthEncodedString = this.writeIconvLengthEncodedString;
|
||||
}
|
||||
this.maxAllowedPacket = opts.maxAllowedPacket;
|
||||
this.maxPacketSize = opts.maxAllowedPacket
|
||||
? Math.min(MAX_BUFFER_SIZE, opts.maxAllowedPacket)
|
||||
: 4194304;
|
||||
this.writeHeader(row);
|
||||
}
|
||||
|
||||
datatypeChanged(row) {
|
||||
if (this.datatypes.length !== row.length) return true;
|
||||
for (let r = 0; r < row.length; r++) {
|
||||
if (row[r] !== null) {
|
||||
switch (typeof row[r]) {
|
||||
case 'boolean':
|
||||
if (this.datatypes[r] !== 0x01) return true;
|
||||
break;
|
||||
case 'number':
|
||||
case 'bigint':
|
||||
if (this.datatypes[r] !== 0x0f) return true;
|
||||
break;
|
||||
case 'object':
|
||||
if (Object.prototype.toString.call(row[r]) === '[object Date]') {
|
||||
if (this.datatypes[r] !== 0x0c) return true;
|
||||
} else if (Buffer.isBuffer(row[r])) {
|
||||
if (this.datatypes[r] !== 0xfb) return true;
|
||||
} else if (
|
||||
row[r].type != null &&
|
||||
[
|
||||
'Point',
|
||||
'LineString',
|
||||
'Polygon',
|
||||
'MultiPoint',
|
||||
'MultiLineString',
|
||||
'MultiPolygon',
|
||||
'GeometryCollection'
|
||||
].includes(row[r].type)
|
||||
) {
|
||||
if (this.datatypes[r] !== 0xfb) return true;
|
||||
} else {
|
||||
if (this.datatypes[r] !== 0x0f) return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (this.datatypes[r] !== 0x0f) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
writeHeader(row) {
|
||||
this.buf[this.pos++] = 0xfa;
|
||||
|
||||
//use last prepare command
|
||||
this.buf[this.pos++] = this.statementId;
|
||||
this.buf[this.pos++] = this.statementId >> 8;
|
||||
this.buf[this.pos++] = this.statementId >> 16;
|
||||
this.buf[this.pos++] = this.statementId >> 24;
|
||||
//set bulk flags to Send types to server
|
||||
this.buf[this.pos++] = 0x80;
|
||||
this.buf[this.pos++] = 0x00;
|
||||
|
||||
//send data type (strings)
|
||||
this.datatypes = [];
|
||||
if (row) {
|
||||
for (let r = 0; r < row.length; r++) {
|
||||
if (row[r] === null) {
|
||||
this.buf[this.pos++] = 0x0f;
|
||||
} else {
|
||||
switch (typeof row[r]) {
|
||||
case 'boolean':
|
||||
this.buf[this.pos++] = 0x01;
|
||||
break;
|
||||
case 'bigint':
|
||||
case 'number':
|
||||
this.buf[this.pos++] = 0x0f;
|
||||
break;
|
||||
case 'object':
|
||||
if (Object.prototype.toString.call(row[r]) === '[object Date]') {
|
||||
this.buf[this.pos++] = 0x0c;
|
||||
} else if (Buffer.isBuffer(row[r])) {
|
||||
this.buf[this.pos++] = 0xfb;
|
||||
} else if (
|
||||
row[r].type != null &&
|
||||
[
|
||||
'Point',
|
||||
'LineString',
|
||||
'Polygon',
|
||||
'MultiPoint',
|
||||
'MultiLineString',
|
||||
'MultiPolygon',
|
||||
'GeometryCollection'
|
||||
].includes(row[r].type)
|
||||
) {
|
||||
this.buf[this.pos++] = 0xfb;
|
||||
} else {
|
||||
this.buf[this.pos++] = 0x0f;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.buf[this.pos++] = 0x0f;
|
||||
}
|
||||
}
|
||||
this.datatypes[r] = this.buf[this.pos - 1];
|
||||
this.buf[this.pos++] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
growBuffer(len) {
|
||||
let newCapacity;
|
||||
if (len + this.pos < MEDIUM_BUFFER_SIZE) {
|
||||
newCapacity = MEDIUM_BUFFER_SIZE;
|
||||
} else if (len + this.pos < LARGE_BUFFER_SIZE) {
|
||||
newCapacity = LARGE_BUFFER_SIZE;
|
||||
} else if (len + this.pos < BIG_BUFFER_SIZE) {
|
||||
newCapacity = BIG_BUFFER_SIZE;
|
||||
} else newCapacity = MAX_BUFFER_SIZE;
|
||||
|
||||
if (newCapacity > this.maxPacketSize && this.markPos) {
|
||||
this.flush(false, len);
|
||||
return true;
|
||||
} else {
|
||||
let newBuf = Buffer.allocUnsafe(Math.min(newCapacity));
|
||||
this.buf.copy(newBuf, 0, 0, this.pos);
|
||||
this.buf = newBuf;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
writeLengthStringAscii(val) {
|
||||
let len = val.length;
|
||||
//not enough space remaining
|
||||
if (len >= this.buf.length - this.pos) {
|
||||
let strBuf = Buffer.from(val, 'ascii');
|
||||
return this.writeLengthEncodedBuffer(strBuf);
|
||||
}
|
||||
|
||||
this.writeLength(len);
|
||||
for (let off = 0; off < len; ) {
|
||||
this.buf[this.pos++] = val.charCodeAt(off++);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
writeLength(len) {
|
||||
if (len < 0xfb) {
|
||||
return this.writeInt8(len);
|
||||
} else if (len < 65536) {
|
||||
let flushed = this.writeInt8(0xfc);
|
||||
return this.writeInt16(len) || flushed;
|
||||
} else if (len < 16777216) {
|
||||
let flushed = this.writeInt8(0xfd);
|
||||
return this.writeInt24(len) || flushed;
|
||||
} else {
|
||||
//4 last bytes are filled with 0, packet limitation size is 32 bit integer
|
||||
if (this.pos + 9 >= this.buf.length) {
|
||||
const tmpBuf = Buffer.allocUnsafe(9);
|
||||
tmpBuf[0] = 0xfe;
|
||||
tmpBuf[1] = len;
|
||||
tmpBuf[2] = len >>> 8;
|
||||
tmpBuf[3] = len >>> 16;
|
||||
tmpBuf[4] = len >>> 24;
|
||||
tmpBuf[5] = 0;
|
||||
tmpBuf[6] = 0;
|
||||
tmpBuf[7] = 0;
|
||||
tmpBuf[8] = 0;
|
||||
return this.writeBuffer(tmpBuf);
|
||||
}
|
||||
this.buf[this.pos++] = 0xfe;
|
||||
this.buf[this.pos++] = len;
|
||||
this.buf[this.pos++] = len >>> 8;
|
||||
this.buf[this.pos++] = len >>> 16;
|
||||
this.buf[this.pos++] = len >>> 24;
|
||||
this.buf[this.pos++] = 0;
|
||||
this.buf[this.pos++] = 0;
|
||||
this.buf[this.pos++] = 0;
|
||||
this.buf[this.pos++] = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
writeLengthEncodedBuffer(val) {
|
||||
let valLen = val.length;
|
||||
let flushed = this.writeLength(valLen);
|
||||
return this.writeBuffer(val) || flushed;
|
||||
}
|
||||
|
||||
writeBuffer(val) {
|
||||
let flushed = false;
|
||||
let valLen = val.length;
|
||||
if (valLen > this.buf.length - this.pos) {
|
||||
//makes buffer bigger (up to 16M)
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) flushed = this.growBuffer(valLen * 2);
|
||||
|
||||
//data may still be bigger than buffer.
|
||||
//must flush buffer when full (and reset position to 4)
|
||||
if (valLen > this.buf.length - this.pos) {
|
||||
let tmpPos = this.buf.length - this.pos;
|
||||
val.copy(this.buf, this.pos, 0, tmpPos);
|
||||
this.pos += tmpPos;
|
||||
this.flush(false, valLen - tmpPos);
|
||||
|
||||
while (tmpPos < valLen) {
|
||||
if (this.buf.length - this.pos < valLen - tmpPos) this.growBuffer(valLen - tmpPos);
|
||||
const toWrite = Math.min(valLen - tmpPos, this.buf.length - this.pos);
|
||||
val.copy(this.buf, this.pos, tmpPos, tmpPos + toWrite);
|
||||
tmpPos += toWrite;
|
||||
this.pos += toWrite;
|
||||
if (valLen - tmpPos > 0) this.flush(false, valLen - tmpPos);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//sure to have enough place to use buffer directly
|
||||
val.copy(this.buf, this.pos, 0, valLen);
|
||||
this.pos += valLen;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
writeInt8(value) {
|
||||
let flushed = false;
|
||||
if (this.pos + 1 > this.buf.length) {
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) {
|
||||
flushed = this.growBuffer(1);
|
||||
} else {
|
||||
this.flush(false, 1);
|
||||
this.buf[this.pos++] = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.buf[this.pos++] = value;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
writeInt16(value) {
|
||||
let flushed = false;
|
||||
if (this.pos + 2 > this.buf.length) {
|
||||
if (this.buf.length < this.maxPacketSize) flushed = this.growBuffer(2);
|
||||
if (this.pos + 2 > this.buf.length) {
|
||||
const tmpBuf = Buffer.allocUnsafe(2);
|
||||
tmpBuf[0] = value;
|
||||
tmpBuf[1] = value >>> 8;
|
||||
this.writeBuffer(tmpBuf);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.buf[this.pos++] = value;
|
||||
this.buf[this.pos++] = value >>> 8;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
writeInt24(value) {
|
||||
let flushed = false;
|
||||
if (this.pos + 3 > this.buf.length) {
|
||||
if (this.buf.length < this.maxPacketSize) flushed = this.growBuffer(3);
|
||||
if (this.pos + 3 > this.buf.length) {
|
||||
const tmpBuf = Buffer.allocUnsafe(3);
|
||||
tmpBuf[0] = value;
|
||||
tmpBuf[1] = value >>> 8;
|
||||
tmpBuf[2] = value >>> 16;
|
||||
this.writeBuffer(tmpBuf);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.buf[this.pos++] = value;
|
||||
this.buf[this.pos++] = value >>> 8;
|
||||
this.buf[this.pos++] = value >>> 16;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
writeIconvLengthEncodedString(str) {
|
||||
let buf = Iconv.encode(str, this.encoding);
|
||||
return this.writeLengthEncodedBuffer(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
writeDefaultLengthEncodedString(str) {
|
||||
//javascript use UCS-2 or UTF-16 string internal representation
|
||||
//that means that string to byte will be a maximum of * 3
|
||||
// (4 bytes utf-8 are represented on 2 UTF-16 characters)
|
||||
if (str.length * 3 + 10 < this.buf.length - this.pos) {
|
||||
//reserve position for length indicator
|
||||
const maxLen = str.length * 3;
|
||||
let lengthPos;
|
||||
if (maxLen < 0xfb) {
|
||||
lengthPos = this.pos;
|
||||
this.pos++;
|
||||
} else if (maxLen < 65536) {
|
||||
this.buf[this.pos++] = 0xfc;
|
||||
lengthPos = this.pos;
|
||||
this.pos += 2;
|
||||
} else {
|
||||
//if len was > 16M, would have been > to buffer length
|
||||
this.buf[this.pos++] = 0xfd;
|
||||
lengthPos = this.pos;
|
||||
this.pos += 3;
|
||||
}
|
||||
const prevPos = this.pos;
|
||||
this.pos += this.buf.write(str, this.pos, this.encoding);
|
||||
//write real data length
|
||||
const realLen = this.pos - prevPos;
|
||||
if (maxLen < 0xfb) {
|
||||
this.buf[lengthPos] = realLen;
|
||||
} else if (maxLen < 65536) {
|
||||
this.buf[lengthPos] = realLen;
|
||||
this.buf[lengthPos + 1] = realLen >>> 8;
|
||||
} else {
|
||||
this.buf[lengthPos] = realLen;
|
||||
this.buf[lengthPos + 1] = realLen >>> 8;
|
||||
this.buf[lengthPos + 2] = realLen >>> 16;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//checking real length
|
||||
let flushed = false;
|
||||
let byteLength = Buffer.byteLength(str, this.encoding);
|
||||
if (byteLength + 9 > this.buf.length - this.pos) {
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) flushed = this.growBuffer(byteLength + 9);
|
||||
|
||||
if (byteLength > this.buf.length - this.pos) {
|
||||
//not enough space in buffer, will stream :
|
||||
let strBuf = Buffer.from(str, this.encoding);
|
||||
return this.writeLengthEncodedBuffer(strBuf) || flushed;
|
||||
}
|
||||
}
|
||||
this.writeLength(byteLength);
|
||||
this.pos += this.buf.write(str, this.pos, this.encoding);
|
||||
return flushed;
|
||||
}
|
||||
|
||||
writeBinaryLocalDate(date, opts) {
|
||||
const year = date.getFullYear();
|
||||
const mon = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const hour = date.getHours();
|
||||
const min = date.getMinutes();
|
||||
const sec = date.getSeconds();
|
||||
const ms = date.getMilliseconds();
|
||||
return this._writeBinaryDate(year, mon, day, hour, min, sec, ms);
|
||||
}
|
||||
|
||||
writeBinaryUtcDate(date, opts) {
|
||||
const year = date.getUTCFullYear();
|
||||
const mon = date.getUTCMonth() + 1;
|
||||
const day = date.getUTCDate();
|
||||
const hour = date.getUTCHours();
|
||||
const min = date.getUTCMinutes();
|
||||
const sec = date.getUTCSeconds();
|
||||
const ms = date.getUTCMilliseconds();
|
||||
return this._writeBinaryDate(year, mon, day, hour, min, sec, ms);
|
||||
}
|
||||
|
||||
_writeBinaryDate(year, mon, day, hour, min, sec, ms) {
|
||||
let len = ms === 0 ? 7 : 11;
|
||||
//not enough space remaining
|
||||
if (len + 1 > this.buf.length - this.pos) {
|
||||
let tmpBuf = Buffer.allocUnsafe(len + 1);
|
||||
|
||||
tmpBuf[0] = len;
|
||||
tmpBuf[1] = year;
|
||||
tmpBuf[2] = year >>> 8;
|
||||
tmpBuf[3] = mon;
|
||||
tmpBuf[4] = day;
|
||||
tmpBuf[5] = hour;
|
||||
tmpBuf[6] = min;
|
||||
tmpBuf[7] = sec;
|
||||
if (ms !== 0) {
|
||||
const micro = ms * 1000;
|
||||
tmpBuf[8] = micro;
|
||||
tmpBuf[9] = micro >>> 8;
|
||||
tmpBuf[10] = micro >>> 16;
|
||||
tmpBuf[11] = micro >>> 24;
|
||||
}
|
||||
|
||||
return this.writeBuffer(tmpBuf);
|
||||
}
|
||||
|
||||
this.buf[this.pos] = len;
|
||||
this.buf[this.pos + 1] = year;
|
||||
this.buf[this.pos + 2] = year >>> 8;
|
||||
this.buf[this.pos + 3] = mon;
|
||||
this.buf[this.pos + 4] = day;
|
||||
this.buf[this.pos + 5] = hour;
|
||||
this.buf[this.pos + 6] = min;
|
||||
this.buf[this.pos + 7] = sec;
|
||||
|
||||
if (ms !== 0) {
|
||||
const micro = ms * 1000;
|
||||
this.buf[this.pos + 8] = micro;
|
||||
this.buf[this.pos + 9] = micro >>> 8;
|
||||
this.buf[this.pos + 10] = micro >>> 16;
|
||||
this.buf[this.pos + 11] = micro >>> 24;
|
||||
}
|
||||
this.pos += len + 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
writeBinaryTimezoneDate(date, opts) {
|
||||
const dateZoned = new Date(
|
||||
moment.tz(date, opts.localTz).tz(opts.tz).format('YYYY-MM-DD HH:mm:ss.SSSSSS')
|
||||
);
|
||||
const year = dateZoned.getFullYear();
|
||||
const mon = dateZoned.getMonth() + 1;
|
||||
const day = dateZoned.getDate();
|
||||
const hour = dateZoned.getHours();
|
||||
const min = dateZoned.getMinutes();
|
||||
const sec = dateZoned.getSeconds();
|
||||
const ms = dateZoned.getMilliseconds();
|
||||
return this._writeBinaryDate(year, mon, day, hour, min, sec, ms);
|
||||
}
|
||||
|
||||
mark(isLast, nextRow) {
|
||||
let flushed = false;
|
||||
this.nextRow = nextRow;
|
||||
if (this.singleQuery) {
|
||||
//end of big query that is more than 16M
|
||||
//write single one
|
||||
if (!this.haveErrorResponse) {
|
||||
const packetSendSize =
|
||||
this.pos +
|
||||
(this.singleQuerySequenceNo !== undefined
|
||||
? (this.singleQuerySequenceNo + 1) * MAX_BUFFER_SIZE
|
||||
: 0);
|
||||
if (this.maxAllowedPacket && packetSendSize > this.maxAllowedPacket) {
|
||||
console.log(
|
||||
"will send a packet to db server with size > connection option 'maxAllowedPacket' (size send is " +
|
||||
packetSendSize +
|
||||
') connection might be reset by server'
|
||||
);
|
||||
}
|
||||
this.copyAndFlush(true);
|
||||
flushed = true;
|
||||
this.markPos = undefined;
|
||||
}
|
||||
|
||||
this.singleQuerySequenceNo = undefined;
|
||||
this.singleQueryCompressSequenceNo = undefined;
|
||||
this.singleQuery = false;
|
||||
this.writeHeader(nextRow);
|
||||
this.markPos = undefined;
|
||||
} else {
|
||||
if (!isLast && this.datatypeChanged(nextRow)) {
|
||||
this.markPos = this.pos;
|
||||
this.flushMark();
|
||||
flushed = true;
|
||||
} else if (this.markPos && this.pos > this.maxPacketSize) {
|
||||
//not enough room for current query , flush mark.
|
||||
this.flushMark();
|
||||
flushed = true;
|
||||
} else {
|
||||
//just mark ending query
|
||||
this.markPos = this.pos;
|
||||
if (isLast) {
|
||||
this.flushMark();
|
||||
flushed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flushed;
|
||||
}
|
||||
|
||||
flush(end, remainingLen) {
|
||||
if (this.markPos && !this.singleQuery) {
|
||||
this.flushMark();
|
||||
} else {
|
||||
//one insert is more than 16M, will continue to mono insert, hoping
|
||||
//that max_allowed_packet is sized accordingly to query.
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) {
|
||||
//in this case, connector has default to 4M packet, and a single query size
|
||||
//is > to 4mb. growing buffer to 16M
|
||||
let newBuf = Buffer.allocUnsafe(MAX_BUFFER_SIZE);
|
||||
this.buf.copy(newBuf, 0, 0, this.pos);
|
||||
this.buf = newBuf;
|
||||
} else {
|
||||
if (!this.haveErrorResponse) {
|
||||
if (this.maxAllowedPacket && this.buf.length > this.maxAllowedPacket) {
|
||||
console.log(
|
||||
"will send a packet to server with size > connection option 'maxAllowedPacket' (size send is " +
|
||||
this.pos +
|
||||
') connection might be reset by server'
|
||||
);
|
||||
}
|
||||
this.copyAndFlush(false);
|
||||
|
||||
this.markPos = undefined;
|
||||
if (!this.singleQuery) this.waitingResponseNo++;
|
||||
this.singleQuery = true;
|
||||
this.singleQuerySequenceNo = this.out.cmd.sequenceNo;
|
||||
this.singleQueryCompressSequenceNo = this.out.cmd.compressSequenceNo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flushMark() {
|
||||
let afterMark;
|
||||
if (this.pos !== this.markPos) {
|
||||
afterMark = Buffer.allocUnsafe(this.pos - this.markPos);
|
||||
this.buf.copy(afterMark, 0, this.markPos, this.pos);
|
||||
}
|
||||
|
||||
this.pos = this.markPos;
|
||||
|
||||
if (!this.haveErrorResponse) {
|
||||
this.copyAndFlush(true);
|
||||
this.waitingResponseNo++;
|
||||
}
|
||||
|
||||
this.pos = 4;
|
||||
this.markPos = undefined;
|
||||
if (this.nextRow) this.writeHeader(this.nextRow);
|
||||
if (afterMark) {
|
||||
if (this.buf.length - this.pos < afterMark.length)
|
||||
this.growBuffer(afterMark.length - (this.buf.length - this.pos));
|
||||
afterMark.copy(this.buf, this.pos, 0, afterMark.length);
|
||||
this.pos += afterMark.length;
|
||||
}
|
||||
this.singleQuery = false;
|
||||
this.singleQuerySequenceNo = undefined;
|
||||
this.singleQueryCompressSequenceNo = undefined;
|
||||
}
|
||||
|
||||
copyAndFlush(ended) {
|
||||
this.out.buf = this.buf;
|
||||
this.out.pos = this.pos;
|
||||
if (this.singleQuerySequenceNo !== undefined) {
|
||||
this.out.cmd.sequenceNo = this.singleQuerySequenceNo;
|
||||
this.out.cmd.compressSequenceNo = this.singleQueryCompressSequenceNo;
|
||||
} else {
|
||||
this.out.cmd.sequenceNo = -1;
|
||||
this.out.cmd.compressSequenceNo = -1;
|
||||
}
|
||||
this.out.flushBuffer(ended);
|
||||
if (this.singleQuerySequenceNo !== undefined) {
|
||||
this.singleQuerySequenceNo = this.out.cmd.sequenceNo;
|
||||
this.singleQueryCompressSequenceNo = this.out.cmd.compressSequenceNo;
|
||||
}
|
||||
this.pos = 4;
|
||||
this.buf = Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
endedWithError() {
|
||||
this.haveErrorResponse = true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BulkPacket;
|
||||
141
node_modules/mariadb/lib/io/compression-input-stream.js
generated
vendored
Normal file
141
node_modules/mariadb/lib/io/compression-input-stream.js
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
'use strict';
|
||||
|
||||
const ZLib = require('zlib');
|
||||
const Utils = require('../misc/utils');
|
||||
|
||||
/**
|
||||
* MySQL packet parser
|
||||
* see : https://mariadb.com/kb/en/library/0-packet/
|
||||
*/
|
||||
class CompressionInputStream {
|
||||
constructor(reader, receiveQueue, opts, info) {
|
||||
this.reader = reader;
|
||||
this.receiveQueue = receiveQueue;
|
||||
this.info = info;
|
||||
this.opts = opts;
|
||||
this.header = Buffer.allocUnsafe(7);
|
||||
this.headerLen = 0;
|
||||
this.compressPacketLen = null;
|
||||
this.packetLen = null;
|
||||
this.remainingLen = null;
|
||||
|
||||
this.parts = null;
|
||||
this.partsTotalLen = 0;
|
||||
}
|
||||
|
||||
receivePacket(chunk) {
|
||||
let cmd = this.currentCmd();
|
||||
if (this.opts.debugCompress) {
|
||||
console.log(
|
||||
'<== conn:%d %s (compress)\n%s',
|
||||
this.info.threadId ? this.info.threadId : -1,
|
||||
cmd
|
||||
? cmd.onPacketReceive
|
||||
? cmd.constructor.name + '.' + cmd.onPacketReceive.name
|
||||
: cmd.constructor.name
|
||||
: 'no command',
|
||||
Utils.log(this.opts, chunk, 0, chunk.length, this.header)
|
||||
);
|
||||
}
|
||||
if (cmd) cmd.compressSequenceNo = this.header[3];
|
||||
const unCompressLen = this.header[4] | (this.header[5] << 8) | (this.header[6] << 16);
|
||||
if (unCompressLen === 0) {
|
||||
this.reader.onData(chunk);
|
||||
} else {
|
||||
//use synchronous inflating, to ensure FIFO packet order
|
||||
const unCompressChunk = ZLib.inflateSync(chunk);
|
||||
this.reader.onData(unCompressChunk);
|
||||
}
|
||||
}
|
||||
|
||||
currentCmd() {
|
||||
let cmd;
|
||||
while ((cmd = this.receiveQueue.peek())) {
|
||||
if (cmd.onPacketReceive) return cmd;
|
||||
this.receiveQueue.shift();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
resetHeader() {
|
||||
this.remainingLen = null;
|
||||
this.headerLen = 0;
|
||||
}
|
||||
|
||||
onData(chunk) {
|
||||
let pos = 0;
|
||||
let length;
|
||||
const chunkLen = chunk.length;
|
||||
|
||||
do {
|
||||
if (this.remainingLen) {
|
||||
length = this.remainingLen;
|
||||
} else if (this.headerLen === 0 && chunkLen - pos >= 7) {
|
||||
this.header[0] = chunk[pos];
|
||||
this.header[1] = chunk[pos + 1];
|
||||
this.header[2] = chunk[pos + 2];
|
||||
this.header[3] = chunk[pos + 3];
|
||||
this.header[4] = chunk[pos + 4];
|
||||
this.header[5] = chunk[pos + 5];
|
||||
this.header[6] = chunk[pos + 6];
|
||||
this.headerLen = 7;
|
||||
pos += 7;
|
||||
this.compressPacketLen = this.header[0] + (this.header[1] << 8) + (this.header[2] << 16);
|
||||
this.packetLen = this.header[4] | (this.header[5] << 8) | (this.header[6] << 16);
|
||||
if (this.packetLen === 0) this.packetLen = this.compressPacketLen;
|
||||
length = this.compressPacketLen;
|
||||
} else {
|
||||
length = null;
|
||||
while (chunkLen - pos > 0) {
|
||||
this.header[this.headerLen++] = chunk[pos++];
|
||||
if (this.headerLen === 7) {
|
||||
this.compressPacketLen =
|
||||
this.header[0] + (this.header[1] << 8) + (this.header[2] << 16);
|
||||
this.packetLen = this.header[4] | (this.header[5] << 8) | (this.header[6] << 16);
|
||||
if (this.packetLen === 0) this.packetLen = this.compressPacketLen;
|
||||
length = this.compressPacketLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (length) {
|
||||
if (chunkLen - pos >= length) {
|
||||
const buf = chunk.slice(pos, pos + length);
|
||||
pos += length;
|
||||
if (this.parts) {
|
||||
this.parts.push(buf);
|
||||
this.partsTotalLen += length;
|
||||
|
||||
if (this.compressPacketLen < 0xffffff) {
|
||||
let buf = Buffer.concat(this.parts, this.partsTotalLen);
|
||||
this.parts = null;
|
||||
this.receivePacket(buf);
|
||||
}
|
||||
} else {
|
||||
if (this.compressPacketLen < 0xffffff) {
|
||||
this.receivePacket(buf);
|
||||
} else {
|
||||
this.parts = [buf];
|
||||
this.partsTotalLen = length;
|
||||
}
|
||||
}
|
||||
this.resetHeader();
|
||||
} else {
|
||||
const buf = chunk.slice(pos, chunkLen);
|
||||
if (!this.parts) {
|
||||
this.parts = [buf];
|
||||
this.partsTotalLen = chunkLen - pos;
|
||||
} else {
|
||||
this.parts.push(buf);
|
||||
this.partsTotalLen += chunkLen - pos;
|
||||
}
|
||||
this.remainingLen = length - (chunkLen - pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while (pos < chunkLen);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CompressionInputStream;
|
||||
171
node_modules/mariadb/lib/io/compression-output-stream.js
generated
vendored
Normal file
171
node_modules/mariadb/lib/io/compression-output-stream.js
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
'use strict';
|
||||
|
||||
const Utils = require('../misc/utils');
|
||||
const ZLib = require('zlib');
|
||||
|
||||
//increase by level to avoid buffer copy.
|
||||
const SMALL_BUFFER_SIZE = 2048;
|
||||
const MEDIUM_BUFFER_SIZE = 131072; //128k
|
||||
const LARGE_BUFFER_SIZE = 1048576; //1M
|
||||
const MAX_BUFFER_SIZE = 16777222; //16M + 7
|
||||
|
||||
/**
|
||||
/**
|
||||
* MySQL compression filter.
|
||||
* see https://mariadb.com/kb/en/library/0-packet/#compressed-packet
|
||||
*/
|
||||
class CompressionOutputStream {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param socket current socket
|
||||
* @param opts current connection options
|
||||
* @param info current connection information
|
||||
* @constructor
|
||||
*/
|
||||
constructor(socket, opts, info) {
|
||||
this.info = info;
|
||||
this.opts = opts;
|
||||
this.pos = 7;
|
||||
this.header = Buffer.allocUnsafe(7);
|
||||
this.buf = Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
this.writer = (buffer) => {
|
||||
socket.write(buffer);
|
||||
};
|
||||
}
|
||||
|
||||
growBuffer(len) {
|
||||
let newCapacity;
|
||||
if (len + this.pos < MEDIUM_BUFFER_SIZE) {
|
||||
newCapacity = MEDIUM_BUFFER_SIZE;
|
||||
} else if (len + this.pos < LARGE_BUFFER_SIZE) {
|
||||
newCapacity = LARGE_BUFFER_SIZE;
|
||||
} else newCapacity = MAX_BUFFER_SIZE;
|
||||
|
||||
let newBuf = Buffer.allocUnsafe(newCapacity);
|
||||
this.buf.copy(newBuf, 0, 0, this.pos);
|
||||
this.buf = newBuf;
|
||||
}
|
||||
|
||||
writeBuf(arr, cmd) {
|
||||
let off = 0,
|
||||
len = arr.length;
|
||||
if (len > this.buf.length - this.pos) {
|
||||
if (this.buf.length !== MAX_BUFFER_SIZE) {
|
||||
this.growBuffer(len);
|
||||
}
|
||||
|
||||
//max buffer size
|
||||
if (len > this.buf.length - this.pos) {
|
||||
//not enough space in buffer, will stream :
|
||||
// fill buffer and flush until all data are snd
|
||||
let remainingLen = len;
|
||||
|
||||
while (true) {
|
||||
//filling buffer
|
||||
let lenToFillBuffer = Math.min(MAX_BUFFER_SIZE - this.pos, remainingLen);
|
||||
arr.copy(this.buf, this.pos, off, off + lenToFillBuffer);
|
||||
remainingLen -= lenToFillBuffer;
|
||||
off += lenToFillBuffer;
|
||||
this.pos += lenToFillBuffer;
|
||||
|
||||
if (remainingLen === 0) return;
|
||||
this.flush(false, cmd, remainingLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
arr.copy(this.buf, this.pos, off, off + len);
|
||||
this.pos += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the internal buffer.
|
||||
*/
|
||||
flush(cmdEnd, cmd, remainingLen) {
|
||||
if (this.pos < 1536) {
|
||||
//*******************************************************************************
|
||||
// small packet, no compression
|
||||
//*******************************************************************************
|
||||
|
||||
this.buf[0] = this.pos - 7;
|
||||
this.buf[1] = (this.pos - 7) >>> 8;
|
||||
this.buf[2] = (this.pos - 7) >>> 16;
|
||||
this.buf[3] = ++cmd.compressSequenceNo;
|
||||
this.buf[4] = 0;
|
||||
this.buf[5] = 0;
|
||||
this.buf[6] = 0;
|
||||
|
||||
if (this.opts.debugCompress) {
|
||||
console.log(
|
||||
'==> conn:%d %s (compress)\n%s',
|
||||
this.info.threadId ? this.info.threadId : -1,
|
||||
cmd ? cmd.constructor.name + '(0,' + this.pos + ')' : 'unknown',
|
||||
Utils.log(this.opts, this.buf, 0, this.pos)
|
||||
);
|
||||
}
|
||||
|
||||
this.writer(this.buf.slice(0, this.pos));
|
||||
} else {
|
||||
//*******************************************************************************
|
||||
// compressing packet
|
||||
//*******************************************************************************
|
||||
//use synchronous inflating, to ensure FIFO packet order
|
||||
const compressChunk = ZLib.deflateSync(this.buf.slice(7, this.pos));
|
||||
const compressChunkLen = compressChunk.length;
|
||||
|
||||
this.header[0] = compressChunkLen;
|
||||
this.header[1] = compressChunkLen >>> 8;
|
||||
this.header[2] = compressChunkLen >>> 16;
|
||||
this.header[3] = ++cmd.compressSequenceNo;
|
||||
this.header[4] = this.pos - 7;
|
||||
this.header[5] = (this.pos - 7) >>> 8;
|
||||
this.header[6] = (this.pos - 7) >>> 16;
|
||||
|
||||
if (this.opts.debugCompress) {
|
||||
console.log(
|
||||
'==> conn:%d %s (compress)\n%s',
|
||||
this.info.threadId ? this.info.threadId : -1,
|
||||
cmd ? cmd.constructor.name + '(0,' + this.pos + '=>' + compressChunkLen + ')' : 'unknown',
|
||||
Utils.log(this.opts, compressChunk, 0, compressChunkLen, this.header)
|
||||
);
|
||||
}
|
||||
|
||||
this.writer(this.header);
|
||||
this.writer(compressChunk);
|
||||
if (cmdEnd && this.pos === MAX_BUFFER_SIZE) this.writeEmptyPacket(cmd);
|
||||
this.header = Buffer.allocUnsafe(7);
|
||||
}
|
||||
this.buf = remainingLen
|
||||
? CompressionOutputStream.allocateBuffer(remainingLen)
|
||||
: Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
this.pos = 7;
|
||||
}
|
||||
|
||||
static allocateBuffer(len) {
|
||||
if (len + 4 < SMALL_BUFFER_SIZE) {
|
||||
return Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
} else if (len + 4 < MEDIUM_BUFFER_SIZE) {
|
||||
return Buffer.allocUnsafe(MEDIUM_BUFFER_SIZE);
|
||||
} else if (len + 4 < LARGE_BUFFER_SIZE) {
|
||||
return Buffer.allocUnsafe(LARGE_BUFFER_SIZE);
|
||||
}
|
||||
return Buffer.allocUnsafe(MAX_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
writeEmptyPacket(cmd) {
|
||||
const emptyBuf = Buffer.from([0x00, 0x00, 0x00, cmd.compressSequenceNo, 0x00, 0x00, 0x00]);
|
||||
|
||||
if (this.opts.debugCompress) {
|
||||
console.log(
|
||||
'==> conn:%d %s (compress)\n%s',
|
||||
this.info.threadId ? this.info.threadId : -1,
|
||||
cmd ? cmd.constructor.name + '(0,' + this.pos + ')' : 'unknown',
|
||||
Utils.log(this.opts, emptyBuf, 0, 7)
|
||||
);
|
||||
}
|
||||
|
||||
this.writer(emptyBuf);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CompressionOutputStream;
|
||||
193
node_modules/mariadb/lib/io/packet-input-stream.js
generated
vendored
Normal file
193
node_modules/mariadb/lib/io/packet-input-stream.js
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
'use strict';
|
||||
|
||||
const PacketNodeEncoded = require('./packet-node-encoded');
|
||||
const PacketIconvEncoded = require('./packet-node-iconv');
|
||||
|
||||
const Utils = require('../misc/utils');
|
||||
|
||||
/**
|
||||
* MySQL packet parser
|
||||
* see : https://mariadb.com/kb/en/library/0-packet/
|
||||
*/
|
||||
class PacketInputStream {
|
||||
constructor(unexpectedPacket, receiveQueue, out, opts, info) {
|
||||
this.unexpectedPacket = unexpectedPacket;
|
||||
this.opts = opts;
|
||||
this.receiveQueue = receiveQueue;
|
||||
this.info = info;
|
||||
this.out = out;
|
||||
|
||||
//in case packet is not complete
|
||||
this.header = Buffer.allocUnsafe(4);
|
||||
this.headerLen = 0;
|
||||
this.packetLen = null;
|
||||
this.remainingLen = null;
|
||||
|
||||
this.parts = null;
|
||||
this.partsTotalLen = 0;
|
||||
this.changeEncoding(this.opts.collation);
|
||||
this.changeDebug(this.opts.logPackets, this.opts.debug);
|
||||
this.opts.on('collation', this.changeEncoding.bind(this));
|
||||
this.opts.on('debug', this.changeDebug.bind(this));
|
||||
}
|
||||
|
||||
changeEncoding(collation) {
|
||||
this.encoding = collation.charset;
|
||||
this.packetConstructor = Buffer.isEncoding(this.encoding)
|
||||
? PacketNodeEncoded
|
||||
: PacketIconvEncoded;
|
||||
}
|
||||
|
||||
changeDebug(logPackets, debug) {
|
||||
this.logPackets = logPackets;
|
||||
this.debug = debug;
|
||||
this.receivePacket =
|
||||
this.logPackets || this.debug ? this.receivePacketDebug : this.receivePacketBasic;
|
||||
}
|
||||
|
||||
receivePacketDebug(packet) {
|
||||
let cmd = this.currentCmd();
|
||||
|
||||
if (packet) {
|
||||
const packetStr = Utils.log(this.opts, packet.buf, packet.pos, packet.end, this.header);
|
||||
if (this.opts.logPackets) {
|
||||
this.info.addPacket(
|
||||
'<== conn:' +
|
||||
(this.info.threadId ? this.info.threadId : -1) +
|
||||
' ' +
|
||||
(cmd
|
||||
? cmd.onPacketReceive
|
||||
? cmd.constructor.name + '.' + cmd.onPacketReceive.name
|
||||
: cmd.constructor.name
|
||||
: 'no command') +
|
||||
' (' +
|
||||
packet.pos +
|
||||
',' +
|
||||
packet.end +
|
||||
'))\n' +
|
||||
packetStr
|
||||
);
|
||||
}
|
||||
if (this.opts.debug) {
|
||||
console.log(
|
||||
'<== conn:%d %s (%d,%d)\n%s',
|
||||
this.info.threadId ? this.info.threadId : -1,
|
||||
cmd
|
||||
? cmd.onPacketReceive
|
||||
? cmd.constructor.name + '.' + cmd.onPacketReceive.name
|
||||
: cmd.constructor.name
|
||||
: 'no command',
|
||||
packet.pos,
|
||||
packet.end,
|
||||
packetStr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cmd) {
|
||||
this.unexpectedPacket(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
cmd.sequenceNo = this.header[3];
|
||||
cmd.onPacketReceive(packet, this.out, this.opts, this.info);
|
||||
if (!cmd.onPacketReceive) this.receiveQueue.shift();
|
||||
}
|
||||
|
||||
receivePacketBasic(packet) {
|
||||
let cmd = this.currentCmd();
|
||||
if (!cmd) {
|
||||
this.unexpectedPacket(packet);
|
||||
return;
|
||||
}
|
||||
cmd.sequenceNo = this.header[3];
|
||||
cmd.onPacketReceive(packet, this.out, this.opts, this.info);
|
||||
if (!cmd.onPacketReceive) this.receiveQueue.shift();
|
||||
}
|
||||
|
||||
resetHeader() {
|
||||
this.remainingLen = null;
|
||||
this.headerLen = 0;
|
||||
}
|
||||
|
||||
currentCmd() {
|
||||
let cmd;
|
||||
while ((cmd = this.receiveQueue.peek())) {
|
||||
if (cmd.onPacketReceive) return cmd;
|
||||
this.receiveQueue.shift();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
onData(chunk) {
|
||||
let pos = 0;
|
||||
let length;
|
||||
const chunkLen = chunk.length;
|
||||
|
||||
do {
|
||||
//read header
|
||||
if (this.remainingLen) {
|
||||
length = this.remainingLen;
|
||||
} else if (this.headerLen === 0 && chunkLen - pos >= 4) {
|
||||
this.header[0] = chunk[pos];
|
||||
this.header[1] = chunk[pos + 1];
|
||||
this.header[2] = chunk[pos + 2];
|
||||
this.header[3] = chunk[pos + 3];
|
||||
pos += 4;
|
||||
this.headerLen = 4;
|
||||
this.packetLen = this.header[0] + (this.header[1] << 8) + (this.header[2] << 16);
|
||||
length = this.packetLen;
|
||||
} else {
|
||||
length = null;
|
||||
while (chunkLen - pos > 0) {
|
||||
this.header[this.headerLen++] = chunk[pos++];
|
||||
if (this.headerLen === 4) {
|
||||
this.packetLen = this.header[0] + (this.header[1] << 8) + (this.header[2] << 16);
|
||||
length = this.packetLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (length) {
|
||||
if (chunkLen - pos >= length) {
|
||||
const buf = chunk.slice(pos, pos + length);
|
||||
pos += length;
|
||||
if (this.parts) {
|
||||
this.parts.push(buf);
|
||||
this.partsTotalLen += length;
|
||||
|
||||
if (this.packetLen < 0xffffff) {
|
||||
let buf = Buffer.concat(this.parts, this.partsTotalLen);
|
||||
this.parts = null;
|
||||
const packet = new this.packetConstructor(buf, 0, this.partsTotalLen, this.encoding);
|
||||
this.receivePacket(packet);
|
||||
}
|
||||
} else {
|
||||
if (this.packetLen < 0xffffff) {
|
||||
const packet = new this.packetConstructor(buf, 0, length, this.encoding);
|
||||
this.receivePacket(packet);
|
||||
} else {
|
||||
this.parts = [buf];
|
||||
this.partsTotalLen = length;
|
||||
}
|
||||
}
|
||||
this.resetHeader();
|
||||
} else {
|
||||
const buf = chunk.slice(pos, chunkLen);
|
||||
if (!this.parts) {
|
||||
this.parts = [buf];
|
||||
this.partsTotalLen = chunkLen - pos;
|
||||
} else {
|
||||
this.parts.push(buf);
|
||||
this.partsTotalLen += chunkLen - pos;
|
||||
}
|
||||
this.remainingLen = length - (chunkLen - pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while (pos < chunkLen);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PacketInputStream;
|
||||
36
node_modules/mariadb/lib/io/packet-node-encoded.js
generated
vendored
Normal file
36
node_modules/mariadb/lib/io/packet-node-encoded.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
const Packet = require('./packet');
|
||||
|
||||
class PacketNodeEncoded extends Packet {
|
||||
constructor(buf, pos, end, encoding) {
|
||||
super(buf, pos, end);
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
readStringLength() {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
|
||||
this.pos += len;
|
||||
return this.buf.toString(this.encoding, this.pos - len, this.pos);
|
||||
}
|
||||
|
||||
readString(beg, len) {
|
||||
return this.buf.toString(this.encoding, beg, beg + len);
|
||||
}
|
||||
|
||||
subPacketLengthEncoded() {
|
||||
const len = this.readUnsignedLength();
|
||||
this.skip(len);
|
||||
return new PacketNodeEncoded(this.buf, this.pos - len, this.pos, this.encoding);
|
||||
}
|
||||
|
||||
readStringRemaining() {
|
||||
const str = this.buf.toString(this.encoding, this.pos, this.end);
|
||||
this.pos = this.end;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PacketNodeEncoded;
|
||||
37
node_modules/mariadb/lib/io/packet-node-iconv.js
generated
vendored
Normal file
37
node_modules/mariadb/lib/io/packet-node-iconv.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
const Packet = require('./packet');
|
||||
const Iconv = require('iconv-lite');
|
||||
|
||||
class PacketIconvEncoded extends Packet {
|
||||
constructor(buf, pos, end, encoding) {
|
||||
super(buf, pos, end);
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
readStringLength() {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
|
||||
this.pos += len;
|
||||
return Iconv.decode(this.buf.slice(this.pos - len, this.pos), this.encoding);
|
||||
}
|
||||
|
||||
readString(beg, len) {
|
||||
return Iconv.decode(this.buf.slice(beg, beg + len), this.encoding);
|
||||
}
|
||||
|
||||
subPacketLengthEncoded() {
|
||||
const len = this.readUnsignedLength();
|
||||
this.skip(len);
|
||||
return new PacketIconvEncoded(this.buf, this.pos - len, this.pos, this.encoding);
|
||||
}
|
||||
|
||||
readStringRemaining() {
|
||||
const str = Iconv.decode(this.buf.slice(this.pos, this.end), this.encoding);
|
||||
this.pos = this.end;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PacketIconvEncoded;
|
||||
502
node_modules/mariadb/lib/io/packet-output-stream.js
generated
vendored
Normal file
502
node_modules/mariadb/lib/io/packet-output-stream.js
generated
vendored
Normal file
@@ -0,0 +1,502 @@
|
||||
'use strict';
|
||||
|
||||
const Iconv = require('iconv-lite');
|
||||
const Utils = require('../misc/utils');
|
||||
|
||||
const QUOTE = 0x27;
|
||||
const DBL_QUOTE = 0x22;
|
||||
const ZERO_BYTE = 0x00;
|
||||
const SLASH = 0x5c;
|
||||
|
||||
//increase by level to avoid buffer copy.
|
||||
const SMALL_BUFFER_SIZE = 1024;
|
||||
const MEDIUM_BUFFER_SIZE = 16384; //16k
|
||||
const LARGE_BUFFER_SIZE = 131072; //128k
|
||||
const BIG_BUFFER_SIZE = 1048576; //1M
|
||||
const MAX_BUFFER_SIZE = 16777219; //16M + 4
|
||||
const CHARS_GLOBAL_REGEXP = /[\0\"\'\\\b\n\r\t\u001A]/g; // eslint-disable-line no-control-regex
|
||||
|
||||
/**
|
||||
* MySQL packet builder.
|
||||
*
|
||||
* @param opts options
|
||||
* @param info connection info
|
||||
* @constructor
|
||||
*/
|
||||
class PacketOutputStream {
|
||||
constructor(opts, info) {
|
||||
this.opts = opts;
|
||||
this.info = info;
|
||||
this.pos = 4;
|
||||
this.buf = Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
this.changeEncoding(this.opts.collation);
|
||||
this.changeDebug(this.opts.logPackets, this.opts.debug);
|
||||
|
||||
this.opts.on('collation', this.changeEncoding.bind(this));
|
||||
this.opts.on('debug', this.changeDebug.bind(this));
|
||||
}
|
||||
|
||||
changeEncoding(collation) {
|
||||
this.encoding = collation.charset;
|
||||
if (this.encoding === 'utf8') {
|
||||
this.writeString = this.writeDefaultBufferString;
|
||||
this.writeStringEscapeQuote = this.writeUtf8StringEscapeQuote;
|
||||
} else if (Buffer.isEncoding(this.encoding)) {
|
||||
this.writeString = this.writeDefaultBufferString;
|
||||
this.writeStringEscapeQuote = this.writeDefaultStringEscapeQuote;
|
||||
} else {
|
||||
this.writeString = this.writeDefaultIconvString;
|
||||
this.writeStringEscapeQuote = this.writeDefaultStringEscapeQuote;
|
||||
}
|
||||
}
|
||||
|
||||
changeDebug(logPackets, debug) {
|
||||
this.logPackets = logPackets;
|
||||
this.debug = debug;
|
||||
this.flushBuffer =
|
||||
this.logPackets || this.debug ? this.flushBufferDebug : this.flushBufferBasic;
|
||||
}
|
||||
|
||||
setStream(stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
growBuffer(len) {
|
||||
let newCapacity;
|
||||
if (len + this.pos < MEDIUM_BUFFER_SIZE) {
|
||||
newCapacity = MEDIUM_BUFFER_SIZE;
|
||||
} else if (len + this.pos < LARGE_BUFFER_SIZE) {
|
||||
newCapacity = LARGE_BUFFER_SIZE;
|
||||
} else if (len + this.pos < BIG_BUFFER_SIZE) {
|
||||
newCapacity = BIG_BUFFER_SIZE;
|
||||
} else newCapacity = MAX_BUFFER_SIZE;
|
||||
|
||||
let newBuf = Buffer.allocUnsafe(newCapacity);
|
||||
this.buf.copy(newBuf, 0, 0, this.pos);
|
||||
this.buf = newBuf;
|
||||
}
|
||||
|
||||
startPacket(cmd) {
|
||||
this.cmd = cmd;
|
||||
this.pos = 4;
|
||||
}
|
||||
|
||||
writeInt8(value) {
|
||||
if (this.pos + 1 >= this.buf.length) {
|
||||
if (this.pos >= MAX_BUFFER_SIZE) {
|
||||
//buffer is more than a Packet, must flushBuffer()
|
||||
this.flushBuffer(false, 1);
|
||||
} else this.growBuffer(1);
|
||||
}
|
||||
this.buf[this.pos++] = value;
|
||||
}
|
||||
|
||||
writeInt16(value) {
|
||||
if (this.pos + 2 >= this.buf.length) {
|
||||
let b = Buffer.allocUnsafe(2);
|
||||
b.writeUInt16LE(value, 0);
|
||||
this.writeBuffer(b, 0, 2);
|
||||
return;
|
||||
}
|
||||
this.buf[this.pos] = value;
|
||||
this.buf[this.pos + 1] = value >> 8;
|
||||
this.pos += 2;
|
||||
}
|
||||
|
||||
writeInt16AtPos(initPos) {
|
||||
this.buf[initPos] = this.pos - initPos - 2;
|
||||
this.buf[initPos + 1] = (this.pos - initPos - 2) >> 8;
|
||||
}
|
||||
|
||||
writeInt32(value) {
|
||||
if (this.pos + 4 >= this.buf.length) {
|
||||
//not enough space remaining
|
||||
let arr = Buffer.allocUnsafe(4);
|
||||
arr.writeInt32LE(value, 0);
|
||||
this.writeBuffer(arr, 0, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
this.buf[this.pos] = value;
|
||||
this.buf[this.pos + 1] = value >> 8;
|
||||
this.buf[this.pos + 2] = value >> 16;
|
||||
this.buf[this.pos + 3] = value >> 24;
|
||||
this.pos += 4;
|
||||
}
|
||||
|
||||
writeLengthCoded(len) {
|
||||
//length encoded can be null(0xfb) or bigger than 65k, but only if using binary protocol
|
||||
//so not implemented for now
|
||||
if (len < 0xfb) {
|
||||
this.writeInt8(len);
|
||||
return;
|
||||
}
|
||||
|
||||
//max length is len < 0xffff
|
||||
this.writeInt8(0xfc);
|
||||
this.writeInt16(len);
|
||||
}
|
||||
|
||||
writeBuffer(arr, off, len) {
|
||||
if (len > this.buf.length - this.pos) {
|
||||
if (this.buf.length !== MAX_BUFFER_SIZE) {
|
||||
this.growBuffer(len);
|
||||
}
|
||||
|
||||
//max buffer size
|
||||
if (len > this.buf.length - this.pos) {
|
||||
//not enough space in buffer, will stream :
|
||||
// fill buffer and flush until all data are snd
|
||||
let remainingLen = len;
|
||||
|
||||
while (true) {
|
||||
//filling buffer
|
||||
let lenToFillBuffer = Math.min(MAX_BUFFER_SIZE - this.pos, remainingLen);
|
||||
arr.copy(this.buf, this.pos, off, off + lenToFillBuffer);
|
||||
remainingLen -= lenToFillBuffer;
|
||||
off += lenToFillBuffer;
|
||||
this.pos += lenToFillBuffer;
|
||||
|
||||
if (remainingLen === 0) return;
|
||||
this.flushBuffer(false, remainingLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
arr.copy(this.buf, this.pos, off, off + len);
|
||||
this.pos += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write ascii string to socket (no escaping)
|
||||
*
|
||||
* @param str string
|
||||
*/
|
||||
writeStringAscii(str) {
|
||||
let len = str.length;
|
||||
|
||||
//not enough space remaining
|
||||
if (len >= this.buf.length - this.pos) {
|
||||
let strBuf = Buffer.from(str, 'ascii');
|
||||
this.writeBuffer(strBuf, 0, strBuf.length);
|
||||
return;
|
||||
}
|
||||
|
||||
for (let off = 0; off < len; ) {
|
||||
this.buf[this.pos++] = str.charCodeAt(off++);
|
||||
}
|
||||
}
|
||||
|
||||
writeUtf8StringEscapeQuote(str) {
|
||||
const charsLength = str.length;
|
||||
|
||||
//not enough space remaining
|
||||
if (charsLength * 3 + 2 >= this.buf.length - this.pos) {
|
||||
const arr = Buffer.from(str, 'utf8');
|
||||
this.writeInt8(QUOTE);
|
||||
this.writeBufferEscape(arr);
|
||||
this.writeInt8(QUOTE);
|
||||
return;
|
||||
}
|
||||
|
||||
//create UTF-8 byte array
|
||||
//since javascript char are internally using UTF-16 using surrogate's pattern, 4 bytes unicode characters will
|
||||
//represent 2 characters : example "\uD83C\uDFA4" = 🎤 unicode 8 "no microphones"
|
||||
//so max size is 3 * charLength
|
||||
//(escape characters are 1 byte encoded, so length might only be 2 when escaped)
|
||||
// + 2 for the quotes for text protocol
|
||||
let charsOffset = 0;
|
||||
let currChar;
|
||||
this.buf[this.pos++] = QUOTE;
|
||||
//quick loop if only ASCII chars for faster escape
|
||||
for (
|
||||
;
|
||||
charsOffset < charsLength && (currChar = str.charCodeAt(charsOffset)) < 0x80;
|
||||
charsOffset++
|
||||
) {
|
||||
if (
|
||||
currChar === SLASH ||
|
||||
currChar === QUOTE ||
|
||||
currChar === ZERO_BYTE ||
|
||||
currChar === DBL_QUOTE
|
||||
) {
|
||||
this.buf[this.pos++] = SLASH;
|
||||
}
|
||||
this.buf[this.pos++] = currChar;
|
||||
}
|
||||
|
||||
//if quick loop not finished
|
||||
while (charsOffset < charsLength) {
|
||||
currChar = str.charCodeAt(charsOffset++);
|
||||
if (currChar < 0x80) {
|
||||
if (
|
||||
currChar === SLASH ||
|
||||
currChar === QUOTE ||
|
||||
currChar === ZERO_BYTE ||
|
||||
currChar === DBL_QUOTE
|
||||
) {
|
||||
this.buf[this.pos++] = SLASH;
|
||||
}
|
||||
this.buf[this.pos++] = currChar;
|
||||
} else if (currChar < 0x800) {
|
||||
this.buf[this.pos++] = 0xc0 | (currChar >> 6);
|
||||
this.buf[this.pos++] = 0x80 | (currChar & 0x3f);
|
||||
} else if (currChar >= 0xd800 && currChar < 0xe000) {
|
||||
//reserved for surrogate - see https://en.wikipedia.org/wiki/UTF-16
|
||||
if (currChar < 0xdc00) {
|
||||
//is high surrogate
|
||||
if (charsOffset + 1 > charsLength) {
|
||||
this.buf[this.pos++] = 0x3f;
|
||||
} else {
|
||||
const nextChar = str.charCodeAt(charsOffset);
|
||||
if (nextChar >= 0xdc00 && nextChar < 0xe000) {
|
||||
//is low surrogate
|
||||
const surrogatePairs =
|
||||
(currChar << 10) + nextChar + (0x010000 - (0xd800 << 10) - 0xdc00);
|
||||
this.buf[this.pos++] = 0xf0 | (surrogatePairs >> 18);
|
||||
this.buf[this.pos++] = 0x80 | ((surrogatePairs >> 12) & 0x3f);
|
||||
this.buf[this.pos++] = 0x80 | ((surrogatePairs >> 6) & 0x3f);
|
||||
this.buf[this.pos++] = 0x80 | (surrogatePairs & 0x3f);
|
||||
charsOffset++;
|
||||
} else {
|
||||
//must have low surrogate
|
||||
this.buf[this.pos++] = 0x3f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//low surrogate without high surrogate before
|
||||
this.buf[this.pos++] = 0x3f;
|
||||
}
|
||||
} else {
|
||||
this.buf[this.pos++] = 0xe0 | (currChar >> 12);
|
||||
this.buf[this.pos++] = 0x80 | ((currChar >> 6) & 0x3f);
|
||||
this.buf[this.pos++] = 0x80 | (currChar & 0x3f);
|
||||
}
|
||||
}
|
||||
this.buf[this.pos++] = QUOTE;
|
||||
}
|
||||
|
||||
writeDefaultBufferString(str) {
|
||||
//javascript use UCS-2 or UTF-16 string internal representation
|
||||
//that means that string to byte will be a maximum of * 3
|
||||
// (4 bytes utf-8 are represented on 2 UTF-16 characters)
|
||||
if (str.length * 3 < this.buf.length - this.pos) {
|
||||
this.pos += this.buf.write(str, this.pos, this.encoding);
|
||||
return;
|
||||
}
|
||||
|
||||
//checking real length
|
||||
let byteLength = Buffer.byteLength(str, this.encoding);
|
||||
if (byteLength > this.buf.length - this.pos) {
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) {
|
||||
this.growBuffer(byteLength);
|
||||
}
|
||||
if (byteLength > this.buf.length - this.pos) {
|
||||
//not enough space in buffer, will stream :
|
||||
let strBuf = Buffer.from(str, this.encoding);
|
||||
this.writeBuffer(strBuf, 0, strBuf.length);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.pos += this.buf.write(str, this.pos, this.encoding);
|
||||
}
|
||||
|
||||
writeDefaultIconvString(str) {
|
||||
let buf = Iconv.encode(str, this.encoding);
|
||||
this.writeBuffer(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters need to be properly escaped :
|
||||
* following characters are to be escaped by "\" :
|
||||
* - \0
|
||||
* - \\
|
||||
* - \'
|
||||
* - \"
|
||||
* regex split part of string writing part, and escaping special char.
|
||||
* Those chars are <= 7f meaning that this will work even with multi-byte encoding
|
||||
*
|
||||
* @param str string to escape.
|
||||
*/
|
||||
writeDefaultStringEscapeQuote(str) {
|
||||
this.writeInt8(QUOTE);
|
||||
let match;
|
||||
let lastIndex = 0;
|
||||
while ((match = CHARS_GLOBAL_REGEXP.exec(str)) !== null) {
|
||||
this.writeString(str.slice(lastIndex, match.index));
|
||||
this.writeInt8(SLASH);
|
||||
this.writeInt8(match[0].charCodeAt(0));
|
||||
lastIndex = CHARS_GLOBAL_REGEXP.lastIndex;
|
||||
}
|
||||
|
||||
if (lastIndex === 0) {
|
||||
// Nothing was escaped
|
||||
this.writeString(str);
|
||||
this.writeInt8(QUOTE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastIndex < str.length) {
|
||||
this.writeString(str.slice(lastIndex));
|
||||
}
|
||||
this.writeInt8(QUOTE);
|
||||
}
|
||||
|
||||
writeBufferEscape(val) {
|
||||
let valLen = val.length;
|
||||
if (valLen * 2 > this.buf.length - this.pos) {
|
||||
//makes buffer bigger (up to 16M)
|
||||
if (this.buf.length !== MAX_BUFFER_SIZE) this.growBuffer(valLen * 2);
|
||||
|
||||
//data may still be bigger than buffer.
|
||||
//must flush buffer when full (and reset position to 4)
|
||||
if (valLen * 2 > this.buf.length - this.pos) {
|
||||
//not enough space in buffer, will fill buffer
|
||||
for (let i = 0; i < valLen; i++) {
|
||||
switch (val[i]) {
|
||||
case QUOTE:
|
||||
case SLASH:
|
||||
case DBL_QUOTE:
|
||||
case ZERO_BYTE:
|
||||
if (this.pos >= this.buf.length) this.flushBuffer(false, (valLen - i) * 2);
|
||||
this.buf[this.pos++] = SLASH; //add escape slash
|
||||
}
|
||||
if (this.pos >= this.buf.length) this.flushBuffer(false, (valLen - i) * 2);
|
||||
this.buf[this.pos++] = val[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//sure to have enough place to use buffer directly
|
||||
for (let i = 0; i < valLen; i++) {
|
||||
switch (val[i]) {
|
||||
case QUOTE:
|
||||
case SLASH:
|
||||
case DBL_QUOTE:
|
||||
case ZERO_BYTE:
|
||||
this.buf[this.pos++] = SLASH; //add escape slash
|
||||
}
|
||||
this.buf[this.pos++] = val[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if buffer contain any data.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isEmpty() {
|
||||
return this.pos <= 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the internal buffer.
|
||||
*/
|
||||
flushBufferDebug(commandEnd, remainingLen) {
|
||||
this.buf[0] = this.pos - 4;
|
||||
this.buf[1] = (this.pos - 4) >>> 8;
|
||||
this.buf[2] = (this.pos - 4) >>> 16;
|
||||
this.buf[3] = ++this.cmd.sequenceNo;
|
||||
|
||||
this.stream.writeBuf(this.buf.slice(0, this.pos), this.cmd);
|
||||
|
||||
const packet = Utils.log(this.opts, this.buf, 0, this.pos);
|
||||
if (this.opts.logPackets) {
|
||||
this.info.addPacket(
|
||||
'==> conn:' +
|
||||
(this.info.threadId ? this.info.threadId : -1) +
|
||||
' ' +
|
||||
this.cmd.constructor.name +
|
||||
'(0,' +
|
||||
this.pos +
|
||||
')\n' +
|
||||
packet
|
||||
);
|
||||
}
|
||||
|
||||
if (this.opts.debug) {
|
||||
console.log(
|
||||
'==> conn:%d %s\n%s',
|
||||
this.info.threadId ? this.info.threadId : -1,
|
||||
this.cmd.constructor.name + '(0,' + this.pos + ')',
|
||||
Utils.log(this.opts, this.buf, 0, this.pos)
|
||||
);
|
||||
}
|
||||
|
||||
if (commandEnd) {
|
||||
//if last packet fill the max size, must send an empty com to indicate that command end.
|
||||
if (this.pos === MAX_BUFFER_SIZE) {
|
||||
this.writeEmptyPacket();
|
||||
} else {
|
||||
this.stream.flush(true, this.cmd);
|
||||
this.buf = Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
}
|
||||
} else {
|
||||
this.buf = allocateBuffer(remainingLen + 4);
|
||||
this.pos = 4;
|
||||
}
|
||||
}
|
||||
|
||||
flushBufferBasic(commandEnd, remainingLen) {
|
||||
this.buf[0] = this.pos - 4;
|
||||
this.buf[1] = (this.pos - 4) >>> 8;
|
||||
this.buf[2] = (this.pos - 4) >>> 16;
|
||||
this.buf[3] = ++this.cmd.sequenceNo;
|
||||
this.stream.writeBuf(this.buf.slice(0, this.pos), this.cmd);
|
||||
if (commandEnd) {
|
||||
//if last packet fill the max size, must send an empty com to indicate that command end.
|
||||
if (this.pos === MAX_BUFFER_SIZE) {
|
||||
this.writeEmptyPacket();
|
||||
} else {
|
||||
this.stream.flush(true, this.cmd);
|
||||
this.buf = Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
}
|
||||
} else {
|
||||
this.buf = allocateBuffer(remainingLen + 4);
|
||||
this.pos = 4;
|
||||
}
|
||||
}
|
||||
|
||||
writeEmptyPacket() {
|
||||
const emptyBuf = Buffer.from([0x00, 0x00, 0x00, ++this.cmd.sequenceNo]);
|
||||
|
||||
if (this.opts.logPackets || this.opts.debug) {
|
||||
const packet = Utils.log(this.opts, emptyBuf, 0, 4);
|
||||
if (this.opts.logPackets) {
|
||||
this.info.addPacket(
|
||||
'==> conn:' +
|
||||
(this.info.threadId ? this.info.threadId : -1) +
|
||||
' ' +
|
||||
this.cmd.constructor.name +
|
||||
'(0,4)\n' +
|
||||
packet
|
||||
);
|
||||
}
|
||||
if (this.opts.debug) {
|
||||
console.log(
|
||||
'==> conn:%d %s\n%s',
|
||||
this.info.threadId ? this.info.threadId : -1,
|
||||
this.cmd.constructor.name + '(0,4)',
|
||||
packet
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.stream.writeBuf(emptyBuf, this.cmd);
|
||||
this.stream.flush(true, this.cmd);
|
||||
}
|
||||
}
|
||||
|
||||
function allocateBuffer(len) {
|
||||
if (len < SMALL_BUFFER_SIZE) {
|
||||
return Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
} else if (len < MEDIUM_BUFFER_SIZE) {
|
||||
return Buffer.allocUnsafe(MEDIUM_BUFFER_SIZE);
|
||||
} else if (len < LARGE_BUFFER_SIZE) {
|
||||
return Buffer.allocUnsafe(LARGE_BUFFER_SIZE);
|
||||
} else if (len < BIG_BUFFER_SIZE) {
|
||||
return Buffer.allocUnsafe(BIG_BUFFER_SIZE);
|
||||
}
|
||||
return Buffer.allocUnsafe(MAX_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
module.exports = PacketOutputStream;
|
||||
509
node_modules/mariadb/lib/io/packet.js
generated
vendored
Normal file
509
node_modules/mariadb/lib/io/packet.js
generated
vendored
Normal file
@@ -0,0 +1,509 @@
|
||||
'use strict';
|
||||
|
||||
const Errors = require('../misc/errors');
|
||||
const Iconv = require('iconv-lite');
|
||||
const Long = require('long');
|
||||
const moment = require('moment-timezone');
|
||||
|
||||
/**
|
||||
* Object to easily parse buffer.
|
||||
*
|
||||
*/
|
||||
class Packet {
|
||||
constructor(buf, pos, end) {
|
||||
this.buf = buf;
|
||||
this.pos = pos;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
skip(n) {
|
||||
this.pos += n;
|
||||
}
|
||||
|
||||
readGeometry(dataTypeName) {
|
||||
const geoBuf = this.readBufferLengthEncoded();
|
||||
if (geoBuf === null || geoBuf.length === 0) {
|
||||
if (dataTypeName) {
|
||||
switch (dataTypeName) {
|
||||
case 'point':
|
||||
return { type: 'Point' };
|
||||
case 'linestring':
|
||||
return { type: 'LineString' };
|
||||
case 'polygon':
|
||||
return { type: 'Polygon' };
|
||||
case 'multipoint':
|
||||
return { type: 'MultiPoint' };
|
||||
case 'multilinestring':
|
||||
return { type: 'MultiLineString' };
|
||||
case 'multipolygon':
|
||||
return { type: 'MultiPolygon' };
|
||||
default:
|
||||
return { type: dataTypeName };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
let geoPos = 4;
|
||||
return readGeometryObject(false);
|
||||
|
||||
function parseCoordinates(byteOrder) {
|
||||
geoPos += 16;
|
||||
const x = byteOrder ? geoBuf.readDoubleLE(geoPos - 16) : geoBuf.readDoubleBE(geoPos - 16);
|
||||
const y = byteOrder ? geoBuf.readDoubleLE(geoPos - 8) : geoBuf.readDoubleBE(geoPos - 8);
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
function readGeometryObject(inner) {
|
||||
const byteOrder = geoBuf[geoPos++];
|
||||
const wkbType = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
|
||||
geoPos += 4;
|
||||
switch (wkbType) {
|
||||
case 1: //wkbPoint
|
||||
const coords = parseCoordinates(byteOrder);
|
||||
|
||||
if (inner) return coords;
|
||||
return {
|
||||
type: 'Point',
|
||||
coordinates: coords
|
||||
};
|
||||
|
||||
case 2: //wkbLineString
|
||||
const pointNumber = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
|
||||
geoPos += 4;
|
||||
let coordinates = [];
|
||||
for (let i = 0; i < pointNumber; i++) {
|
||||
coordinates.push(parseCoordinates(byteOrder));
|
||||
}
|
||||
if (inner) return coordinates;
|
||||
return {
|
||||
type: 'LineString',
|
||||
coordinates: coordinates
|
||||
};
|
||||
|
||||
case 3: //wkbPolygon
|
||||
let polygonCoordinates = [];
|
||||
const numRings = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
|
||||
geoPos += 4;
|
||||
for (let ring = 0; ring < numRings; ring++) {
|
||||
const pointNumber = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
|
||||
geoPos += 4;
|
||||
let linesCoordinates = [];
|
||||
for (let i = 0; i < pointNumber; i++) {
|
||||
linesCoordinates.push(parseCoordinates(byteOrder));
|
||||
}
|
||||
polygonCoordinates.push(linesCoordinates);
|
||||
}
|
||||
|
||||
if (inner) return polygonCoordinates;
|
||||
return {
|
||||
type: 'Polygon',
|
||||
coordinates: polygonCoordinates
|
||||
};
|
||||
|
||||
case 4: //wkbMultiPoint
|
||||
return {
|
||||
type: 'MultiPoint',
|
||||
coordinates: parseGeomArray(byteOrder, true)
|
||||
};
|
||||
|
||||
case 5: //wkbMultiLineString
|
||||
return {
|
||||
type: 'MultiLineString',
|
||||
coordinates: parseGeomArray(byteOrder, true)
|
||||
};
|
||||
case 6: //wkbMultiPolygon
|
||||
return {
|
||||
type: 'MultiPolygon',
|
||||
coordinates: parseGeomArray(byteOrder, true)
|
||||
};
|
||||
case 7: //wkbGeometryCollection
|
||||
return {
|
||||
type: 'GeometryCollection',
|
||||
geometries: parseGeomArray(byteOrder, false)
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseGeomArray(byteOrder, inner) {
|
||||
let coordinates = [];
|
||||
const number = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
|
||||
geoPos += 4;
|
||||
for (let i = 0; i < number; i++) {
|
||||
coordinates.push(readGeometryObject(inner));
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
}
|
||||
|
||||
peek() {
|
||||
return this.buf[this.pos];
|
||||
}
|
||||
|
||||
remaining() {
|
||||
return this.end - this.pos > 0;
|
||||
}
|
||||
|
||||
readUInt8() {
|
||||
return this.buf[this.pos++];
|
||||
}
|
||||
|
||||
readUInt16() {
|
||||
return this.buf[this.pos++] + (this.buf[this.pos++] << 8);
|
||||
}
|
||||
|
||||
readUInt24() {
|
||||
return this.buf[this.pos++] + (this.buf[this.pos++] << 8) + (this.buf[this.pos++] << 16);
|
||||
}
|
||||
|
||||
readUInt32() {
|
||||
return (
|
||||
this.buf[this.pos++] +
|
||||
(this.buf[this.pos++] << 8) +
|
||||
(this.buf[this.pos++] << 16) +
|
||||
this.buf[this.pos++] * 0x1000000
|
||||
);
|
||||
}
|
||||
|
||||
readInt32() {
|
||||
return (
|
||||
this.buf[this.pos++] +
|
||||
(this.buf[this.pos++] << 8) +
|
||||
(this.buf[this.pos++] << 16) +
|
||||
(this.buf[this.pos++] << 24)
|
||||
);
|
||||
}
|
||||
|
||||
readInt32LE() {
|
||||
return (
|
||||
(this.buf[this.pos++] << 24) +
|
||||
(this.buf[this.pos++] << 16) +
|
||||
(this.buf[this.pos++] << 8) +
|
||||
this.buf[this.pos++]
|
||||
);
|
||||
}
|
||||
|
||||
readInt64() {
|
||||
// could use readBigInt64LE when support would be 10.20+
|
||||
const val =
|
||||
this.buf[this.pos + 4] +
|
||||
this.buf[this.pos + 5] * 2 ** 8 +
|
||||
this.buf[this.pos + 6] * 2 ** 16 +
|
||||
(this.buf[this.pos + 7] << 24);
|
||||
const vv =
|
||||
(BigInt(val) << BigInt(32)) +
|
||||
BigInt(
|
||||
this.buf[this.pos] +
|
||||
this.buf[this.pos + 1] * 2 ** 8 +
|
||||
this.buf[this.pos + 2] * 2 ** 16 +
|
||||
this.buf[this.pos + 3] * 2 ** 24
|
||||
);
|
||||
this.pos += 8;
|
||||
return vv;
|
||||
}
|
||||
|
||||
readUnsignedLength() {
|
||||
const type = this.buf[this.pos++] & 0xff;
|
||||
switch (type) {
|
||||
case 0xfb:
|
||||
return null;
|
||||
case 0xfc:
|
||||
return this.readUInt16();
|
||||
case 0xfd:
|
||||
return this.readUInt24();
|
||||
case 0xfe:
|
||||
// limitation to BigInt signed value
|
||||
return Number(this.readInt64());
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
readBuffer(len) {
|
||||
this.pos += len;
|
||||
return this.buf.slice(this.pos - len, this.pos);
|
||||
}
|
||||
|
||||
readBufferRemaining() {
|
||||
let b = this.buf.slice(this.pos, this.end);
|
||||
this.pos = this.end;
|
||||
return b;
|
||||
}
|
||||
|
||||
readBufferLengthEncoded() {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
this.pos += len;
|
||||
return this.buf.slice(this.pos - len, this.pos);
|
||||
}
|
||||
|
||||
readStringNullEnded() {
|
||||
let initialPosition = this.pos;
|
||||
let cnt = 0;
|
||||
while (this.remaining() > 0 && this.buf[this.pos++] !== 0) {
|
||||
cnt++;
|
||||
}
|
||||
return this.buf.toString('utf8', initialPosition, initialPosition + cnt);
|
||||
}
|
||||
|
||||
readSignedLength() {
|
||||
const type = this.buf[this.pos++];
|
||||
switch (type) {
|
||||
case 0xfb:
|
||||
return null;
|
||||
case 0xfc:
|
||||
return this.readUInt16();
|
||||
case 0xfd:
|
||||
return this.readUInt24();
|
||||
case 0xfe:
|
||||
return Number(this.readInt64());
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
readSignedLengthBigInt() {
|
||||
const type = this.buf[this.pos++];
|
||||
switch (type) {
|
||||
case 0xfb:
|
||||
return null;
|
||||
case 0xfc:
|
||||
return BigInt(this.readUInt16());
|
||||
case 0xfd:
|
||||
return BigInt(this.readUInt24());
|
||||
case 0xfe:
|
||||
return this.readInt64();
|
||||
default:
|
||||
return BigInt(type);
|
||||
}
|
||||
}
|
||||
|
||||
readAsciiStringLengthEncoded() {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
this.pos += len;
|
||||
return this.buf.toString('ascii', this.pos - len, this.pos);
|
||||
}
|
||||
|
||||
readStringLengthEncoded(encoding) {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
|
||||
this.pos += len;
|
||||
if (Buffer.isEncoding(encoding)) {
|
||||
return this.buf.toString(encoding, this.pos - len, this.pos);
|
||||
}
|
||||
return Iconv.decode(this.buf.slice(this.pos - len, this.pos), encoding);
|
||||
}
|
||||
|
||||
readLongLengthEncoded(supportBigInt, supportBigNumbers, bigNumberStrings, unsigned) {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
|
||||
if (supportBigInt) {
|
||||
const str = this.buf.toString('ascii', this.pos, this.pos + len);
|
||||
this.pos += len;
|
||||
return BigInt(str);
|
||||
}
|
||||
|
||||
let result = 0;
|
||||
let negate = false;
|
||||
let begin = this.pos;
|
||||
|
||||
//minus sign
|
||||
if (len > 0 && this.buf[begin] === 45) {
|
||||
negate = true;
|
||||
begin++;
|
||||
}
|
||||
for (; begin < this.pos + len; begin++) {
|
||||
result = result * 10 + (this.buf[begin] - 48);
|
||||
}
|
||||
|
||||
let val = negate ? -1 * result : result;
|
||||
this.pos += len;
|
||||
|
||||
if (!Number.isSafeInteger(val)) {
|
||||
const str = this.buf.toString('ascii', this.pos - len, this.pos);
|
||||
if (bigNumberStrings) return str;
|
||||
if (supportBigNumbers) {
|
||||
return Long.fromString(str, unsigned, 10);
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
readDecimalLengthEncoded(bigNumberStrings) {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
|
||||
this.pos += len;
|
||||
let str = this.buf.toString('ascii', this.pos - len, this.pos);
|
||||
return bigNumberStrings ? str : +str;
|
||||
}
|
||||
|
||||
readDate() {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
|
||||
let res = [];
|
||||
let value = 0;
|
||||
let initPos = this.pos;
|
||||
this.pos += len;
|
||||
while (initPos < this.pos) {
|
||||
const char = this.buf[initPos++];
|
||||
if (char === 45) {
|
||||
//minus separator
|
||||
res.push(value);
|
||||
value = 0;
|
||||
} else {
|
||||
value = value * 10 + char - 48;
|
||||
}
|
||||
}
|
||||
res.push(value);
|
||||
|
||||
//handle zero-date as null
|
||||
if (res[0] === 0 && res[1] === 0 && res[2] === 0) return null;
|
||||
|
||||
return new Date(res[0], res[1] - 1, res[2]);
|
||||
}
|
||||
|
||||
readDateTime(opts) {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
this.pos += len;
|
||||
const str = this.buf.toString('ascii', this.pos - len, this.pos);
|
||||
if (str.startsWith('0000-00-00 00:00:00')) return null;
|
||||
|
||||
if (opts.tz) {
|
||||
return new Date(
|
||||
moment.tz(str, opts.tz).clone().tz(opts.localTz).format('YYYY-MM-DD HH:mm:ss.SSSSSS')
|
||||
);
|
||||
}
|
||||
return new Date(str);
|
||||
}
|
||||
|
||||
readIntLengthEncoded() {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
|
||||
let result = 0;
|
||||
let negate = false;
|
||||
let begin = this.pos;
|
||||
|
||||
if (len > 0 && this.buf[begin] === 45) {
|
||||
//minus sign
|
||||
negate = true;
|
||||
begin++;
|
||||
}
|
||||
for (; begin < this.pos + len; begin++) {
|
||||
result = result * 10 + (this.buf[begin] - 48);
|
||||
}
|
||||
this.pos += len;
|
||||
return negate ? -1 * result : result;
|
||||
}
|
||||
|
||||
readFloatLengthCoded() {
|
||||
const len = this.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
this.pos += len;
|
||||
return +this.buf.toString('ascii', this.pos - len, this.pos);
|
||||
}
|
||||
|
||||
skipLengthCodedNumber() {
|
||||
const type = this.buf[this.pos++] & 0xff;
|
||||
switch (type) {
|
||||
case 251:
|
||||
return;
|
||||
case 252:
|
||||
this.pos +=
|
||||
2 + (0xffff & ((this.buf[this.pos] & 0xff) + ((this.buf[this.pos + 1] & 0xff) << 8)));
|
||||
return;
|
||||
case 253:
|
||||
this.pos +=
|
||||
3 +
|
||||
(0xffffff &
|
||||
((this.buf[this.pos] & 0xff) +
|
||||
((this.buf[this.pos + 1] & 0xff) << 8) +
|
||||
((this.buf[this.pos + 2] & 0xff) << 16)));
|
||||
return;
|
||||
case 254:
|
||||
this.pos +=
|
||||
8 +
|
||||
((this.buf[this.pos] & 0xff) +
|
||||
((this.buf[this.pos + 1] & 0xff) << 8) +
|
||||
((this.buf[this.pos + 2] & 0xff) << 16) +
|
||||
((this.buf[this.pos + 3] & 0xff) << 24) +
|
||||
((this.buf[this.pos + 4] & 0xff) << 32) +
|
||||
((this.buf[this.pos + 5] & 0xff) << 40) +
|
||||
((this.buf[this.pos + 6] & 0xff) << 48) +
|
||||
((this.buf[this.pos + 7] & 0xff) << 56));
|
||||
return;
|
||||
default:
|
||||
this.pos += type;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
positionFromEnd(num) {
|
||||
this.pos = this.end - num;
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing purpose only
|
||||
*/
|
||||
_toBuf() {
|
||||
return this.buf.slice(this.pos, this.end);
|
||||
}
|
||||
|
||||
forceOffset(off) {
|
||||
this.pos = off;
|
||||
}
|
||||
|
||||
length() {
|
||||
return this.end - this.pos;
|
||||
}
|
||||
|
||||
subPacketLengthEncoded() {
|
||||
const len = this.readUnsignedLength();
|
||||
this.skip(len);
|
||||
return new Packet(this.buf, this.pos - len, this.pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse ERR_Packet : https://mariadb.com/kb/en/library/err_packet/
|
||||
*
|
||||
* @param info current connection info
|
||||
* @param sql command sql
|
||||
* @param stack additional stack trace
|
||||
* @returns {Error}
|
||||
*/
|
||||
readError(info, sql, stack) {
|
||||
this.skip(1);
|
||||
let errorCode = this.readUInt16();
|
||||
let sqlState = '';
|
||||
|
||||
if (this.peek() === 0x23) {
|
||||
this.skip(6);
|
||||
sqlState = this.buf.toString('utf8', this.pos - 5, this.pos);
|
||||
}
|
||||
|
||||
let msg = this.buf.toString('utf8', this.pos, this.end);
|
||||
if (sql) msg += '\n' + sql;
|
||||
let fatal = sqlState.startsWith('08') || sqlState === '70100';
|
||||
if (fatal) {
|
||||
const packetMsgs = info.getLastPackets();
|
||||
if (packetMsgs !== '')
|
||||
return Errors.createError(
|
||||
msg + '\nlast received packets:\n' + packetMsgs,
|
||||
fatal,
|
||||
info,
|
||||
sqlState,
|
||||
errorCode,
|
||||
stack
|
||||
);
|
||||
}
|
||||
return Errors.createError(msg, fatal, info, sqlState, errorCode, stack);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Packet;
|
||||
481
node_modules/mariadb/lib/io/rewrite-packet.js
generated
vendored
Normal file
481
node_modules/mariadb/lib/io/rewrite-packet.js
generated
vendored
Normal file
@@ -0,0 +1,481 @@
|
||||
'use strict';
|
||||
|
||||
const Iconv = require('iconv-lite');
|
||||
|
||||
const QUOTE = 0x27;
|
||||
const DBL_QUOTE = 0x22;
|
||||
const ZERO_BYTE = 0x00;
|
||||
const SLASH = 0x5c;
|
||||
|
||||
const SMALL_BUFFER_SIZE = 1024;
|
||||
const MEDIUM_BUFFER_SIZE = 16384; //16k
|
||||
const LARGE_BUFFER_SIZE = 131072; //128k
|
||||
const BIG_BUFFER_SIZE = 1048576; //1M
|
||||
const MAX_BUFFER_SIZE = 16777219; //16M + 4
|
||||
|
||||
const CHARS_GLOBAL_REGEXP = /[\0\"\'\\]/g; // eslint-disable-line no-control-regex
|
||||
|
||||
/**
|
||||
* Packet splitter.
|
||||
*
|
||||
* The servers have a limit max_allowed_packet which limits the size of the data sent, to avoid saturating the server in memory.
|
||||
*
|
||||
* The following implementation has a workaround that will rewrite the command and separate the send according to this value.
|
||||
* This implies that this command can send multiple commands, with some tricks for sequencing packets.
|
||||
*
|
||||
*/
|
||||
class ReWritePacket {
|
||||
constructor(maxAllowedPacket, out, initString, endString) {
|
||||
this.out = out;
|
||||
this.buf = Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
this.pos = 4;
|
||||
this.initStr = initString;
|
||||
this.endStr = endString;
|
||||
this.encoding = out.encoding;
|
||||
this.endStrLength = Buffer.byteLength(this.endStr, this.encoding);
|
||||
this.waitingResponseNo = 0;
|
||||
this.singleQuery = false;
|
||||
this.haveErrorResponse = false;
|
||||
|
||||
if (this.encoding === 'utf8') {
|
||||
this.writeString = this.writeDefaultBufferString;
|
||||
this.writeStringEscapeQuote = this.writeUtf8StringEscapeQuote;
|
||||
} else if (Buffer.isEncoding(this.encoding)) {
|
||||
this.writeString = this.writeDefaultBufferString;
|
||||
this.writeStringEscapeQuote = this.writeDefaultStringEscapeQuote;
|
||||
} else {
|
||||
this.writeString = this.writeDefaultIconvString;
|
||||
this.writeStringEscapeQuote = this.writeDefaultStringEscapeQuote;
|
||||
}
|
||||
this.maxAllowedPacket = maxAllowedPacket;
|
||||
if (maxAllowedPacket) {
|
||||
this.maxPacketSize = Math.min(MAX_BUFFER_SIZE, maxAllowedPacket) - this.endStrLength;
|
||||
} else this.maxPacketSize = 4194304 - this.endStrLength;
|
||||
|
||||
this.buf[this.pos++] = 0x03;
|
||||
this.writeString(this.initStr);
|
||||
}
|
||||
|
||||
growBuffer(len) {
|
||||
let newCapacity;
|
||||
if (len + this.pos < MEDIUM_BUFFER_SIZE) {
|
||||
newCapacity = MEDIUM_BUFFER_SIZE;
|
||||
} else if (len + this.pos < LARGE_BUFFER_SIZE) {
|
||||
newCapacity = LARGE_BUFFER_SIZE;
|
||||
} else if (len + this.pos < BIG_BUFFER_SIZE) {
|
||||
newCapacity = BIG_BUFFER_SIZE;
|
||||
} else newCapacity = MAX_BUFFER_SIZE;
|
||||
|
||||
if (newCapacity > this.maxPacketSize && this.markPos) {
|
||||
this.flush(false, len);
|
||||
return true;
|
||||
}
|
||||
let newBuf = Buffer.allocUnsafe(Math.min(newCapacity));
|
||||
this.buf.copy(newBuf, 0, 0, this.pos);
|
||||
this.buf = newBuf;
|
||||
return false;
|
||||
}
|
||||
|
||||
writeInt8(value) {
|
||||
let flushed = false;
|
||||
if (this.pos + 1 + this.endStrLength >= this.buf.length) {
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) {
|
||||
flushed = this.growBuffer(1);
|
||||
} else {
|
||||
this.flush(false, 1);
|
||||
this.buf[this.pos++] = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.buf[this.pos++] = value;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write ascii string to socket (no escaping)
|
||||
*
|
||||
* @param str string
|
||||
*/
|
||||
writeStringAscii(str) {
|
||||
let len = str.length;
|
||||
|
||||
//not enough space remaining
|
||||
if (len >= this.buf.length - (this.pos + this.endStrLength)) {
|
||||
let strBuf = Buffer.from(str, 'ascii');
|
||||
return this.writeBuffer(strBuf, 0, strBuf.length);
|
||||
}
|
||||
|
||||
for (let off = 0; off < len; ) {
|
||||
this.buf[this.pos++] = str.charCodeAt(off++);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
writeUtf8StringEscapeQuote(str) {
|
||||
const charsLength = str.length;
|
||||
|
||||
//not enough space remaining
|
||||
if (charsLength * 3 + 2 >= this.buf.length - (this.pos + this.endStrLength)) {
|
||||
let flushed;
|
||||
const arr = Buffer.from(str, 'utf8');
|
||||
flushed = this.writeInt8(QUOTE);
|
||||
flushed = this.writeBufferEscape(arr) || flushed;
|
||||
flushed = this.writeInt8(QUOTE) || flushed;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
//create UTF-8 byte array
|
||||
//since javascript char are internally using UTF-16 using surrogate's pattern, 4 bytes unicode characters will
|
||||
//represent 2 characters : example "\uD83C\uDFA4" = 🎤 unicode 8 "no microphones"
|
||||
//so max size is 3 * charLength
|
||||
//(escape characters are 1 byte encoded, so length might only be 2 when escaped)
|
||||
// + 2 for the quotes for text protocol
|
||||
let charsOffset = 0;
|
||||
let currChar;
|
||||
this.buf[this.pos++] = QUOTE;
|
||||
//quick loop if only ASCII chars for faster escape
|
||||
for (
|
||||
;
|
||||
charsOffset < charsLength && (currChar = str.charCodeAt(charsOffset)) < 0x80;
|
||||
charsOffset++
|
||||
) {
|
||||
if (
|
||||
currChar === SLASH ||
|
||||
currChar === QUOTE ||
|
||||
currChar === ZERO_BYTE ||
|
||||
currChar === DBL_QUOTE
|
||||
) {
|
||||
this.buf[this.pos++] = SLASH;
|
||||
}
|
||||
this.buf[this.pos++] = currChar;
|
||||
}
|
||||
|
||||
//if quick loop not finished
|
||||
while (charsOffset < charsLength) {
|
||||
currChar = str.charCodeAt(charsOffset++);
|
||||
if (currChar < 0x80) {
|
||||
if (
|
||||
currChar === SLASH ||
|
||||
currChar === QUOTE ||
|
||||
currChar === ZERO_BYTE ||
|
||||
currChar === DBL_QUOTE
|
||||
) {
|
||||
this.buf[this.pos++] = SLASH;
|
||||
}
|
||||
this.buf[this.pos++] = currChar;
|
||||
} else if (currChar < 0x800) {
|
||||
this.buf[this.pos++] = 0xc0 | (currChar >> 6);
|
||||
this.buf[this.pos++] = 0x80 | (currChar & 0x3f);
|
||||
} else if (currChar >= 0xd800 && currChar < 0xe000) {
|
||||
//reserved for surrogate - see https://en.wikipedia.org/wiki/UTF-16
|
||||
if (currChar < 0xdc00) {
|
||||
//is high surrogate
|
||||
if (charsOffset + 1 > charsLength) {
|
||||
this.buf[this.pos++] = 0x3f;
|
||||
} else {
|
||||
const nextChar = str.charCodeAt(charsOffset);
|
||||
if (nextChar >= 0xdc00 && nextChar < 0xe000) {
|
||||
//is low surrogate
|
||||
const surrogatePairs =
|
||||
(currChar << 10) + nextChar + (0x010000 - (0xd800 << 10) - 0xdc00);
|
||||
this.buf[this.pos++] = 0xf0 | (surrogatePairs >> 18);
|
||||
this.buf[this.pos++] = 0x80 | ((surrogatePairs >> 12) & 0x3f);
|
||||
this.buf[this.pos++] = 0x80 | ((surrogatePairs >> 6) & 0x3f);
|
||||
this.buf[this.pos++] = 0x80 | (surrogatePairs & 0x3f);
|
||||
charsOffset++;
|
||||
} else {
|
||||
//must have low surrogate
|
||||
this.buf[this.pos++] = 0x3f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//low surrogate without high surrogate before
|
||||
this.buf[this.pos++] = 0x3f;
|
||||
}
|
||||
} else {
|
||||
this.buf[this.pos++] = 0xe0 | (currChar >> 12);
|
||||
this.buf[this.pos++] = 0x80 | ((currChar >> 6) & 0x3f);
|
||||
this.buf[this.pos++] = 0x80 | (currChar & 0x3f);
|
||||
}
|
||||
}
|
||||
this.buf[this.pos++] = QUOTE;
|
||||
return false;
|
||||
}
|
||||
|
||||
writeDefaultIconvString(str) {
|
||||
let buf = Iconv.encode(str, this.encoding);
|
||||
return this.writeBuffer(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
writeDefaultBufferString(str) {
|
||||
//javascript use UCS-2 or UTF-16 string internal representation
|
||||
//that means that string to byte will be a maximum of * 3
|
||||
// (4 bytes utf-8 are represented on 2 UTF-16 characters)
|
||||
if (str.length * 3 < this.buf.length - (this.pos + this.endStrLength)) {
|
||||
this.pos += this.buf.write(str, this.pos, this.encoding);
|
||||
return false;
|
||||
}
|
||||
|
||||
//checking real length
|
||||
let flushed = false;
|
||||
let byteLength = Buffer.byteLength(str, this.encoding);
|
||||
if (byteLength > this.buf.length - (this.pos + this.endStrLength)) {
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) {
|
||||
flushed = this.growBuffer(byteLength);
|
||||
}
|
||||
if (byteLength > this.buf.length - (this.pos + this.endStrLength)) {
|
||||
//not enough space in buffer, will stream :
|
||||
let strBuf = Buffer.from(str, this.encoding);
|
||||
flushed = this.writeBuffer(strBuf, 0, strBuf.length) || flushed;
|
||||
return flushed;
|
||||
}
|
||||
}
|
||||
this.pos += this.buf.write(str, this.pos, this.encoding);
|
||||
return flushed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters need to be properly escaped :
|
||||
* following characters are to be escaped by "\" :
|
||||
* - \0
|
||||
* - \\
|
||||
* - \'
|
||||
* - \"
|
||||
* regex split part of string writing part, and escaping special char.
|
||||
* Those chars are <= 7f meaning that this will work even with multi-byte encoding
|
||||
*
|
||||
* @param str string to escape.
|
||||
*/
|
||||
writeDefaultStringEscapeQuote(str) {
|
||||
let flushed = this.writeInt8(QUOTE);
|
||||
let match;
|
||||
let lastIndex = 0;
|
||||
while ((match = CHARS_GLOBAL_REGEXP.exec(str)) !== null) {
|
||||
flushed = this.writeString(str.slice(lastIndex, match.index)) || flushed;
|
||||
flushed = this.writeInt8(SLASH) || flushed;
|
||||
flushed = this.writeInt8(match[0].charCodeAt(0)) || flushed;
|
||||
lastIndex = CHARS_GLOBAL_REGEXP.lastIndex;
|
||||
}
|
||||
|
||||
if (lastIndex === 0) {
|
||||
// Nothing was escaped
|
||||
flushed = this.writeString(str) || flushed;
|
||||
flushed = this.writeInt8(QUOTE) || flushed;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
if (lastIndex < str.length) {
|
||||
flushed = this.writeString(str.slice(lastIndex)) || flushed;
|
||||
}
|
||||
flushed = this.writeInt8(QUOTE) || flushed;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
writeBufferEscape(val) {
|
||||
let flushed = false;
|
||||
let valLen = val.length;
|
||||
if (valLen * 2 > this.buf.length - (this.pos + this.endStrLength)) {
|
||||
//makes buffer bigger (up to 16M)
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) flushed = this.growBuffer(valLen * 2);
|
||||
|
||||
//data may still be bigger than buffer.
|
||||
//must flush buffer when full (and reset position to 4)
|
||||
if (valLen * 2 > this.buf.length - (this.pos + this.endStrLength)) {
|
||||
//not enough space in buffer, will fill buffer
|
||||
for (let i = 0; i < valLen; i++) {
|
||||
switch (val[i]) {
|
||||
case QUOTE:
|
||||
case SLASH:
|
||||
case DBL_QUOTE:
|
||||
case ZERO_BYTE:
|
||||
if (this.pos >= this.buf.length) this.flush(false, (valLen - i) * 2);
|
||||
this.buf[this.pos++] = SLASH; //add escape slash
|
||||
}
|
||||
if (this.pos >= this.buf.length) this.flush(false, (valLen - i) * 2);
|
||||
this.buf[this.pos++] = val[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//sure to have enough place to use buffer directly
|
||||
for (let i = 0; i < valLen; i++) {
|
||||
switch (val[i]) {
|
||||
case QUOTE:
|
||||
case SLASH:
|
||||
case DBL_QUOTE:
|
||||
case ZERO_BYTE:
|
||||
this.buf[this.pos++] = SLASH; //add escape slash
|
||||
}
|
||||
this.buf[this.pos++] = val[i];
|
||||
}
|
||||
return flushed;
|
||||
}
|
||||
|
||||
writeBuffer(arr, off, len) {
|
||||
let flushed = false;
|
||||
if (len > this.buf.length - (this.pos + this.endStrLength)) {
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) flushed = this.growBuffer(len);
|
||||
|
||||
//max buffer size
|
||||
if (len > this.buf.length - (this.pos + this.endStrLength)) {
|
||||
//not enough space in buffer, will stream :
|
||||
// fill buffer and flush until all data are snd
|
||||
let remainingLen = len;
|
||||
|
||||
while (true) {
|
||||
//filling buffer
|
||||
let lenToFillBuffer = Math.min(MAX_BUFFER_SIZE - this.pos, remainingLen);
|
||||
arr.copy(this.buf, this.pos, off, off + lenToFillBuffer);
|
||||
remainingLen -= lenToFillBuffer;
|
||||
off += lenToFillBuffer;
|
||||
this.pos += lenToFillBuffer;
|
||||
|
||||
if (remainingLen === 0) return flushed;
|
||||
this.flush(false, remainingLen);
|
||||
flushed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
arr.copy(this.buf, this.pos, off, off + len);
|
||||
this.pos += len;
|
||||
return flushed;
|
||||
}
|
||||
|
||||
mark(isLast) {
|
||||
let flushed = false;
|
||||
if (this.singleQuery) {
|
||||
//end of big query that is more than 16M
|
||||
//write single one
|
||||
flushed = this.writeString(this.endStr);
|
||||
|
||||
if (!this.haveErrorResponse) {
|
||||
const packetSendSize =
|
||||
this.pos +
|
||||
(this.singleQuerySequenceNo != undefined
|
||||
? (this.singleQuerySequenceNo + 1) * MAX_BUFFER_SIZE
|
||||
: 0);
|
||||
if (this.maxAllowedPacket && packetSendSize > this.maxAllowedPacket) {
|
||||
console.log(
|
||||
"will send a packet to db server with size > connection option 'maxAllowedPacket' (size send is " +
|
||||
packetSendSize +
|
||||
') connection might be reset by server'
|
||||
);
|
||||
}
|
||||
this.copyAndFlush(true);
|
||||
flushed = true;
|
||||
this.markPos = undefined;
|
||||
}
|
||||
|
||||
this.singleQuerySequenceNo = undefined;
|
||||
this.singleQueryCompressSequenceNo = undefined;
|
||||
this.singleQuery = false;
|
||||
this.buf[this.pos++] = 0x03;
|
||||
this.writeString(this.initStr);
|
||||
this.markPos = undefined;
|
||||
} else {
|
||||
if (this.markPos && this.pos + this.endStrLength > this.maxPacketSize) {
|
||||
//not enough room for current query, flush mark.
|
||||
this.flushMark();
|
||||
flushed = true;
|
||||
}
|
||||
//just mark ending query
|
||||
this.markPos = this.pos;
|
||||
if (isLast) {
|
||||
this.flushMark();
|
||||
flushed = true;
|
||||
}
|
||||
if (!isLast) flushed = this.writeStringAscii(',') || flushed;
|
||||
}
|
||||
return flushed;
|
||||
}
|
||||
|
||||
flush(end, remainingLen) {
|
||||
if (this.markPos && !this.singleQuery) {
|
||||
this.flushMark();
|
||||
} else {
|
||||
//one insert is more than 16M, will continue to mono insert, hoping
|
||||
//that max_allowed_packet is sized accordingly to query.
|
||||
if (this.buf.length < MAX_BUFFER_SIZE) {
|
||||
//in this case, connector has default to 4M packet, and a single query size
|
||||
//is > to 4mb. growing buffer to 16M
|
||||
let newBuf = Buffer.allocUnsafe(MAX_BUFFER_SIZE);
|
||||
this.buf.copy(newBuf, 0, 0, this.pos);
|
||||
this.buf = newBuf;
|
||||
} else {
|
||||
if (!this.haveErrorResponse) {
|
||||
if (this.maxAllowedPacket && this.buf.length > this.maxAllowedPacket) {
|
||||
console.log(
|
||||
"will send a packet to server with size > connection option 'maxAllowedPacket' (size send is " +
|
||||
this.pos +
|
||||
') connection might be reset by server'
|
||||
);
|
||||
}
|
||||
this.copyAndFlush(false);
|
||||
|
||||
this.markPos = undefined;
|
||||
if (!this.singleQuery) this.waitingResponseNo++;
|
||||
this.singleQuery = true;
|
||||
this.singleQuerySequenceNo = this.out.cmd.sequenceNo;
|
||||
this.singleQueryCompressSequenceNo = this.out.cmd.compressSequenceNo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flushMark() {
|
||||
let afterMark;
|
||||
if (this.pos !== this.markPos) {
|
||||
//remove "," character
|
||||
afterMark = Buffer.allocUnsafe(this.pos - this.markPos - 1);
|
||||
this.buf.copy(afterMark, 0, this.markPos + 1, this.pos);
|
||||
}
|
||||
|
||||
this.pos = this.markPos;
|
||||
this.writeString(this.endStr);
|
||||
|
||||
if (!this.haveErrorResponse) {
|
||||
this.copyAndFlush(true);
|
||||
this.waitingResponseNo++;
|
||||
}
|
||||
|
||||
this.pos = 4;
|
||||
this.buf[this.pos++] = 0x03;
|
||||
this.writeString(this.initStr);
|
||||
this.markPos = undefined;
|
||||
if (afterMark) {
|
||||
if (this.buf.length - this.pos < afterMark.length)
|
||||
this.growBuffer(afterMark.length - (this.buf.length - this.pos));
|
||||
afterMark.copy(this.buf, this.pos, 0, afterMark.length);
|
||||
this.pos += afterMark.length;
|
||||
}
|
||||
this.singleQuery = false;
|
||||
this.singleQuerySequenceNo = undefined;
|
||||
this.singleQueryCompressSequenceNo = undefined;
|
||||
}
|
||||
|
||||
copyAndFlush(ended) {
|
||||
this.out.buf = this.buf;
|
||||
this.out.pos = this.pos;
|
||||
if (this.singleQuerySequenceNo != undefined) {
|
||||
this.out.cmd.sequenceNo = this.singleQuerySequenceNo;
|
||||
this.out.cmd.compressSequenceNo = this.singleQueryCompressSequenceNo;
|
||||
} else {
|
||||
this.out.cmd.sequenceNo = -1;
|
||||
this.out.cmd.compressSequenceNo = -1;
|
||||
}
|
||||
this.out.flushBuffer(ended);
|
||||
if (this.singleQuerySequenceNo != undefined) {
|
||||
this.singleQuerySequenceNo = this.out.cmd.sequenceNo;
|
||||
this.singleQueryCompressSequenceNo = this.out.cmd.compressSequenceNo;
|
||||
}
|
||||
this.pos = 4;
|
||||
this.buf = Buffer.allocUnsafe(SMALL_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
endedWithError() {
|
||||
this.haveErrorResponse = true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReWritePacket;
|
||||
96
node_modules/mariadb/lib/misc/connection-information.js
generated
vendored
Normal file
96
node_modules/mariadb/lib/misc/connection-information.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
'use strict';
|
||||
const Queue = require('denque');
|
||||
|
||||
const _addPacket = function (msg) {
|
||||
this.lastPackets.push(msg);
|
||||
while (this.lastPackets.size() > 32) this.lastPackets.shift();
|
||||
};
|
||||
|
||||
const _getLastPackets = function () {
|
||||
let output = '';
|
||||
let packet;
|
||||
while ((packet = this.lastPackets.shift())) {
|
||||
output += '\n' + packet;
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
class ConnectionInformation {
|
||||
constructor() {
|
||||
this.threadId = -1;
|
||||
this.status = null;
|
||||
this.serverVersion = null;
|
||||
this.serverCapabilities = null;
|
||||
}
|
||||
|
||||
addPacket(msg) {}
|
||||
|
||||
getLastPackets() {
|
||||
return '';
|
||||
}
|
||||
|
||||
enableLogPacket() {
|
||||
this.lastPackets = new Queue();
|
||||
this.addPacket = _addPacket.bind(this);
|
||||
this.getLastPackets = _getLastPackets.bind(this);
|
||||
}
|
||||
|
||||
hasMinVersion(major, minor, patch) {
|
||||
if (!this.serverVersion)
|
||||
throw new Error('cannot know if server version until connection is established');
|
||||
|
||||
if (!major) throw new Error('a major version must be set');
|
||||
|
||||
if (!minor) minor = 0;
|
||||
if (!patch) patch = 0;
|
||||
|
||||
let ver = this.serverVersion;
|
||||
return (
|
||||
ver.major > major ||
|
||||
(ver.major === major && ver.minor > minor) ||
|
||||
(ver.major === major && ver.minor === minor && ver.patch >= patch)
|
||||
);
|
||||
}
|
||||
|
||||
isMariaDB() {
|
||||
if (!this.serverVersion)
|
||||
throw new Error('cannot know if server is MariaDB until connection is established');
|
||||
return this.serverVersion.mariaDb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse raw info to set server major/minor/patch values
|
||||
* @param info
|
||||
*/
|
||||
static parseVersionString(info) {
|
||||
let car;
|
||||
let offset = 0;
|
||||
let type = 0;
|
||||
let val = 0;
|
||||
|
||||
for (; offset < info.serverVersion.raw.length; offset++) {
|
||||
car = info.serverVersion.raw.charCodeAt(offset);
|
||||
if (car < 48 || car > 57) {
|
||||
switch (type) {
|
||||
case 0:
|
||||
info.serverVersion.major = val;
|
||||
break;
|
||||
case 1:
|
||||
info.serverVersion.minor = val;
|
||||
break;
|
||||
case 2:
|
||||
info.serverVersion.patch = val;
|
||||
return;
|
||||
}
|
||||
type++;
|
||||
val = 0;
|
||||
} else {
|
||||
val = val * 10 + car - 48;
|
||||
}
|
||||
}
|
||||
//serverVersion finished by number like "5.5.57", assign patchVersion
|
||||
if (type === 2) info.serverVersion.patch = val;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ConnectionInformation;
|
||||
116
node_modules/mariadb/lib/misc/errors.js
generated
vendored
Normal file
116
node_modules/mariadb/lib/misc/errors.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
'use strict';
|
||||
const ErrorCodes = require('../const/error-code');
|
||||
|
||||
class SqlError extends Error {
|
||||
constructor(msg, fatal, info, sqlState, errno, additionalStack, addHeader) {
|
||||
super(
|
||||
(addHeader === undefined || addHeader
|
||||
? '(conn=' +
|
||||
(info ? (info.threadId ? info.threadId : -1) : -1) +
|
||||
', no: ' +
|
||||
(errno ? errno : -1) +
|
||||
', SQLState: ' +
|
||||
(sqlState ? sqlState : 'HY000') +
|
||||
') '
|
||||
: '') + msg
|
||||
);
|
||||
this.fatal = fatal;
|
||||
this.errno = errno;
|
||||
this.sqlState = sqlState;
|
||||
if (errno > 45000 && errno < 46000) {
|
||||
//driver error
|
||||
this.code = errByNo[errno] || 'UNKNOWN';
|
||||
} else {
|
||||
this.code = ErrorCodes.codes[this.errno] || 'UNKNOWN';
|
||||
}
|
||||
if (additionalStack) {
|
||||
//adding caller stack, removing initial "Error:\n"
|
||||
this.stack +=
|
||||
'\n From event:\n' + additionalStack.substring(additionalStack.indexOf('\n') + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error factory, so error get connection information.
|
||||
*
|
||||
* @param msg current error message
|
||||
* @param fatal is error fatal
|
||||
* @param info connection information
|
||||
* @param sqlState sql state
|
||||
* @param errno error number
|
||||
* @param additionalStack additional stack trace to see
|
||||
* @param addHeader add connection information
|
||||
* @returns {Error} the error
|
||||
*/
|
||||
module.exports.createError = function (
|
||||
msg,
|
||||
fatal,
|
||||
info,
|
||||
sqlState,
|
||||
errno,
|
||||
additionalStack,
|
||||
addHeader
|
||||
) {
|
||||
return new SqlError(msg, fatal, info, sqlState, errno, additionalStack, addHeader);
|
||||
};
|
||||
|
||||
/********************************************************************************
|
||||
* Driver specific errors
|
||||
********************************************************************************/
|
||||
|
||||
module.exports.ER_CONNECTION_ALREADY_CLOSED = 45001;
|
||||
module.exports.ER_ALREADY_CONNECTING = 45002;
|
||||
module.exports.ER_MYSQL_CHANGE_USER_BUG = 45003;
|
||||
module.exports.ER_CMD_NOT_EXECUTED_DESTROYED = 45004;
|
||||
module.exports.ER_NULL_CHAR_ESCAPEID = 45005;
|
||||
module.exports.ER_NULL_ESCAPEID = 45006;
|
||||
module.exports.ER_NOT_IMPLEMENTED_FORMAT = 45007;
|
||||
module.exports.ER_NODE_NOT_SUPPORTED_TLS = 45008;
|
||||
module.exports.ER_SOCKET_UNEXPECTED_CLOSE = 45009;
|
||||
module.exports.ER_UNEXPECTED_PACKET = 45011;
|
||||
module.exports.ER_CONNECTION_TIMEOUT = 45012;
|
||||
module.exports.ER_CMD_CONNECTION_CLOSED = 45013;
|
||||
module.exports.ER_CHANGE_USER_BAD_PACKET = 45014;
|
||||
module.exports.ER_PING_BAD_PACKET = 45015;
|
||||
module.exports.ER_MISSING_PARAMETER = 45016;
|
||||
module.exports.ER_PARAMETER_UNDEFINED = 45017;
|
||||
module.exports.ER_PLACEHOLDER_UNDEFINED = 45018;
|
||||
module.exports.ER_SOCKET = 45019;
|
||||
module.exports.ER_EOF_EXPECTED = 45020;
|
||||
module.exports.ER_LOCAL_INFILE_DISABLED = 45021;
|
||||
module.exports.ER_LOCAL_INFILE_NOT_READABLE = 45022;
|
||||
module.exports.ER_SERVER_SSL_DISABLED = 45023;
|
||||
module.exports.ER_AUTHENTICATION_BAD_PACKET = 45024;
|
||||
module.exports.ER_AUTHENTICATION_PLUGIN_NOT_SUPPORTED = 45025;
|
||||
module.exports.ER_SOCKET_TIMEOUT = 45026;
|
||||
module.exports.ER_POOL_ALREADY_CLOSED = 45027;
|
||||
module.exports.ER_GET_CONNECTION_TIMEOUT = 45028;
|
||||
module.exports.ER_SETTING_SESSION_ERROR = 45029;
|
||||
module.exports.ER_INITIAL_SQL_ERROR = 45030;
|
||||
module.exports.ER_BATCH_WITH_NO_VALUES = 45031;
|
||||
module.exports.ER_RESET_BAD_PACKET = 45032;
|
||||
module.exports.ER_WRONG_IANA_TIMEZONE = 45033;
|
||||
module.exports.ER_LOCAL_INFILE_WRONG_FILENAME = 45034;
|
||||
module.exports.ER_ADD_CONNECTION_CLOSED_POOL = 45035;
|
||||
module.exports.ER_WRONG_AUTO_TIMEZONE = 45036;
|
||||
module.exports.ER_CLOSING_POOL = 45037;
|
||||
module.exports.ER_TIMEOUT_NOT_SUPPORTED = 45038;
|
||||
module.exports.ER_INITIAL_TIMEOUT_ERROR = 45039;
|
||||
module.exports.ER_DUPLICATE_FIELD = 45040;
|
||||
module.exports.ER_CLIENT_OPTION_INCOMPATIBILITY = 45041;
|
||||
module.exports.ER_PING_TIMEOUT = 45042;
|
||||
module.exports.ER_BAD_PARAMETER_VALUE = 45043;
|
||||
module.exports.ER_CANNOT_RETRIEVE_RSA_KEY = 45044;
|
||||
module.exports.ER_MINIMUM_NODE_VERSION_REQUIRED = 45045;
|
||||
|
||||
const keys = Object.keys(module.exports);
|
||||
const errByNo = {};
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const keyName = keys[i];
|
||||
if (keyName !== 'createError') {
|
||||
errByNo[module.exports[keyName]] = keyName;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.SqlError = SqlError;
|
||||
1025
node_modules/mariadb/lib/misc/parse.js
generated
vendored
Normal file
1025
node_modules/mariadb/lib/misc/parse.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
294
node_modules/mariadb/lib/misc/utils.js
generated
vendored
Normal file
294
node_modules/mariadb/lib/misc/utils.js
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
'use strict';
|
||||
const Long = require('long');
|
||||
const hexArray = '0123456789ABCDEF'.split('');
|
||||
const Errors = require('../misc/errors');
|
||||
const CommonText = require('../cmd/common-text-cmd');
|
||||
const Iconv = require('iconv-lite');
|
||||
|
||||
/**
|
||||
* Write bytes/hexadecimal value of a byte array to a string.
|
||||
* String output example :
|
||||
* 38 00 00 00 03 63 72 65 61 74 65 20 74 61 62 6C 8....create tabl
|
||||
* 65 20 42 6C 6F 62 54 65 73 74 63 6C 6F 62 74 65 e BlobTestclobte
|
||||
* 73 74 32 20 28 73 74 72 6D 20 74 65 78 74 29 20 st2 (strm text)
|
||||
* 43 48 41 52 53 45 54 20 75 74 66 38 CHARSET utf8
|
||||
*/
|
||||
module.exports.log = function (opts, buf, off, end, header) {
|
||||
let out = [];
|
||||
if (!buf) return '';
|
||||
if (off === undefined || off === null) off = 0;
|
||||
if (end === undefined || end === null) end = buf.length;
|
||||
let asciiValue = new Array(16);
|
||||
asciiValue[8] = ' ';
|
||||
|
||||
let useHeader = header !== undefined;
|
||||
let offset = off || 0;
|
||||
const maxLgh = Math.min(useHeader ? opts.debugLen - header.length : opts.debugLen, end - offset);
|
||||
const isLimited = end - offset > maxLgh;
|
||||
let byteValue;
|
||||
let posHexa = 0;
|
||||
let pos = 0;
|
||||
|
||||
out.push(
|
||||
'+--------------------------------------------------+\n' +
|
||||
'| 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n' +
|
||||
'+--------------------------------------------------+------------------+\n'
|
||||
);
|
||||
|
||||
if (useHeader) {
|
||||
while (pos < header.length) {
|
||||
if (posHexa === 0) out.push('| ');
|
||||
byteValue = header[pos++] & 0xff;
|
||||
out.push(hexArray[byteValue >>> 4], hexArray[byteValue & 0x0f], ' ');
|
||||
asciiValue[posHexa++] =
|
||||
byteValue > 31 && byteValue < 127 ? String.fromCharCode(byteValue) : '.';
|
||||
if (posHexa === 8) out.push(' ');
|
||||
}
|
||||
}
|
||||
|
||||
pos = offset;
|
||||
while (pos < maxLgh + offset) {
|
||||
if (posHexa === 0) out.push('| ');
|
||||
byteValue = buf[pos] & 0xff;
|
||||
|
||||
out.push(hexArray[byteValue >>> 4], hexArray[byteValue & 0x0f], ' ');
|
||||
|
||||
asciiValue[posHexa++] =
|
||||
byteValue > 31 && byteValue < 127 ? String.fromCharCode(byteValue) : '.';
|
||||
|
||||
if (posHexa === 8) out.push(' ');
|
||||
if (posHexa === 16) {
|
||||
out.push('| ', asciiValue.join(''), ' |\n');
|
||||
posHexa = 0;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
let remaining = posHexa;
|
||||
if (remaining > 0) {
|
||||
if (remaining < 8) {
|
||||
for (; remaining < 8; remaining++) {
|
||||
out.push(' ');
|
||||
asciiValue[posHexa++] = ' ';
|
||||
}
|
||||
out.push(' ');
|
||||
}
|
||||
|
||||
for (; remaining < 16; remaining++) {
|
||||
out.push(' ');
|
||||
asciiValue[posHexa++] = ' ';
|
||||
}
|
||||
|
||||
out.push('| ', asciiValue.join(''), isLimited ? ' |...\n' : ' |\n');
|
||||
} else if (isLimited) {
|
||||
out[out.length - 1] = ' |...\n';
|
||||
}
|
||||
out.push('+--------------------------------------------------+------------------+\n');
|
||||
return out.join('');
|
||||
};
|
||||
|
||||
module.exports.escapeId = (opts, info, value) => {
|
||||
if (!value || value === '') {
|
||||
throw Errors.createError(
|
||||
'Cannot escape empty ID value',
|
||||
false,
|
||||
info,
|
||||
'0A000',
|
||||
Errors.ER_NULL_ESCAPEID
|
||||
);
|
||||
}
|
||||
if (value.includes('\u0000')) {
|
||||
throw Errors.createError(
|
||||
'Cannot escape ID with null character (u0000)',
|
||||
false,
|
||||
info,
|
||||
'0A000',
|
||||
Errors.ER_NULL_CHAR_ESCAPEID
|
||||
);
|
||||
}
|
||||
|
||||
// always return escaped value, event when there is no special characters
|
||||
// to permit working with reserved words
|
||||
if (value.match(/^`.+`$/g)) {
|
||||
// already escaped
|
||||
return value;
|
||||
}
|
||||
return '`' + value.replace(/`/g, '``') + '`';
|
||||
};
|
||||
|
||||
module.exports.escape = (opts, info, value) => {
|
||||
if (value === undefined || value === null) return 'NULL';
|
||||
|
||||
switch (typeof value) {
|
||||
case 'boolean':
|
||||
return value ? 'true' : 'false';
|
||||
case 'bigint':
|
||||
case 'number':
|
||||
return '' + value;
|
||||
case 'object':
|
||||
if (Object.prototype.toString.call(value) === '[object Date]') {
|
||||
return opts.tz
|
||||
? opts.tz === 'Etc/UTC'
|
||||
? CommonText.getUtcDate(value, opts)
|
||||
: CommonText.getTimezoneDate(value, opts)
|
||||
: CommonText.getLocalDate(value, opts);
|
||||
} else if (Buffer.isBuffer(value)) {
|
||||
let stValue;
|
||||
if (Buffer.isEncoding(opts.collation.charset)) {
|
||||
stValue = value.toString(opts.collation.charset, 0, value.length);
|
||||
} else {
|
||||
stValue = Iconv.decode(value, opts.collation.charset);
|
||||
}
|
||||
return "_binary'" + escapeString(stValue) + "'";
|
||||
} else if (typeof value.toSqlString === 'function') {
|
||||
return "'" + escapeString(String(value.toSqlString())) + "'";
|
||||
} else if (Long.isLong(value)) {
|
||||
return value.toString();
|
||||
} else if (Array.isArray(value)) {
|
||||
let out = opts.arrayParenthesis ? '(' : '';
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (i !== 0) out += ',';
|
||||
out += this.escape(opts, info, value[i]);
|
||||
}
|
||||
if (opts.arrayParenthesis) out += ')';
|
||||
return out;
|
||||
} else {
|
||||
if (
|
||||
value.type != null &&
|
||||
[
|
||||
'Point',
|
||||
'LineString',
|
||||
'Polygon',
|
||||
'MultiPoint',
|
||||
'MultiLineString',
|
||||
'MultiPolygon',
|
||||
'GeometryCollection'
|
||||
].includes(value.type)
|
||||
) {
|
||||
//GeoJSON format.
|
||||
let prefix =
|
||||
info &&
|
||||
((info.isMariaDB() && info.hasMinVersion(10, 1, 4)) ||
|
||||
(!info.isMariaDB() && info.hasMinVersion(5, 7, 6)))
|
||||
? 'ST_'
|
||||
: '';
|
||||
switch (value.type) {
|
||||
case 'Point':
|
||||
return (
|
||||
prefix +
|
||||
"PointFromText('POINT(" +
|
||||
CommonText.geoPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
|
||||
case 'LineString':
|
||||
return (
|
||||
prefix +
|
||||
"LineFromText('LINESTRING(" +
|
||||
CommonText.geoArrayPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
|
||||
case 'Polygon':
|
||||
return (
|
||||
prefix +
|
||||
"PolygonFromText('POLYGON(" +
|
||||
CommonText.geoMultiArrayPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
|
||||
case 'MultiPoint':
|
||||
return (
|
||||
prefix +
|
||||
"MULTIPOINTFROMTEXT('MULTIPOINT(" +
|
||||
CommonText.geoArrayPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
|
||||
case 'MultiLineString':
|
||||
return (
|
||||
prefix +
|
||||
"MLineFromText('MULTILINESTRING(" +
|
||||
CommonText.geoMultiArrayPointToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
|
||||
case 'MultiPolygon':
|
||||
return (
|
||||
prefix +
|
||||
"MPolyFromText('MULTIPOLYGON(" +
|
||||
CommonText.geoMultiPolygonToString(value.coordinates) +
|
||||
")')"
|
||||
);
|
||||
|
||||
case 'GeometryCollection':
|
||||
return (
|
||||
prefix +
|
||||
"GeomCollFromText('GEOMETRYCOLLECTION(" +
|
||||
CommonText.geometricCollectionToString(value.geometries) +
|
||||
")')"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (opts.permitSetMultiParamEntries) {
|
||||
let out = '';
|
||||
let first = true;
|
||||
for (let key in value) {
|
||||
const val = value[key];
|
||||
if (typeof val === 'function') continue;
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
out += ',';
|
||||
}
|
||||
out += '`' + key + '`=';
|
||||
out += this.escape(opts, info, val);
|
||||
}
|
||||
if (out === '') return "'" + escapeString(JSON.stringify(value)) + "'";
|
||||
return out;
|
||||
} else {
|
||||
return "'" + escapeString(JSON.stringify(value)) + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return "'" + escapeString(value) + "'";
|
||||
}
|
||||
};
|
||||
|
||||
// see https://mariadb.com/kb/en/library/string-literals/
|
||||
const LITTERAL_ESCAPE = {
|
||||
'\u0000': '\\0',
|
||||
"'": "\\'",
|
||||
'"': '\\"',
|
||||
'\b': '\\b',
|
||||
'\n': '\\n',
|
||||
'\r': '\\r',
|
||||
'\t': '\\t',
|
||||
'\u001A': '\\Z',
|
||||
'\\': '\\\\'
|
||||
};
|
||||
|
||||
const escapeString = (val) => {
|
||||
const pattern = /[\u0000'"\b\n\r\t\u001A\\]/g;
|
||||
|
||||
let offset = 0;
|
||||
let escaped = '';
|
||||
let match;
|
||||
|
||||
while ((match = pattern.exec(val))) {
|
||||
escaped += val.substring(offset, match.index);
|
||||
escaped += LITTERAL_ESCAPE[match[0]];
|
||||
offset = pattern.lastIndex;
|
||||
}
|
||||
|
||||
if (offset === 0) {
|
||||
return val;
|
||||
}
|
||||
|
||||
if (offset < val.length) {
|
||||
escaped += val.substring(offset);
|
||||
}
|
||||
|
||||
return escaped;
|
||||
};
|
||||
590
node_modules/mariadb/lib/pool-base.js
generated
vendored
Normal file
590
node_modules/mariadb/lib/pool-base.js
generated
vendored
Normal file
@@ -0,0 +1,590 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const util = require('util');
|
||||
const Queue = require('denque');
|
||||
const Errors = require('./misc/errors');
|
||||
const Utils = require('./misc/utils');
|
||||
|
||||
function PoolBase(options, processTask, createConnectionPool, pingPromise) {
|
||||
//*****************************************************************
|
||||
// public methods
|
||||
//*****************************************************************
|
||||
|
||||
/**
|
||||
* Retrieve a connection from pool.
|
||||
* Create a new one, if limit is not reached.
|
||||
* wait until acquireTimeout.
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.getConnection = function () {
|
||||
return addRequest(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a query on one connection from pool.
|
||||
*
|
||||
* @param sql sql command
|
||||
* @param value parameter value of sql command (not mandatory)
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.query = function (sql, value) {
|
||||
return addRequest(this, sql, value, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a batch on one connection from pool.
|
||||
*
|
||||
* @param sql sql command
|
||||
* @param value parameter value of sql command (not mandatory)
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.batch = function (sql, value) {
|
||||
return addRequest(this, sql, value, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Close all connection in pool
|
||||
*
|
||||
* @return Promise
|
||||
*/
|
||||
this.end = function () {
|
||||
if (closed) {
|
||||
return Promise.reject(
|
||||
Errors.createError(
|
||||
'pool is already closed',
|
||||
false,
|
||||
null,
|
||||
'HY000',
|
||||
Errors.ER_POOL_ALREADY_CLOSED,
|
||||
undefined,
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
closed = true;
|
||||
clearInterval(idleMaintainingTask);
|
||||
|
||||
//close unused connections
|
||||
const idleConnectionsEndings = [];
|
||||
let conn;
|
||||
while ((conn = idleConnections.shift())) {
|
||||
idleConnectionsEndings.push(conn.forceEnd());
|
||||
}
|
||||
|
||||
firstTaskTimeout = clearTimeout(firstTaskTimeout);
|
||||
|
||||
//reject all waiting task
|
||||
if (taskQueue.size() > 0) {
|
||||
let task;
|
||||
const err = Errors.createError(
|
||||
'pool is ending, connection request aborted',
|
||||
false,
|
||||
null,
|
||||
'HY000',
|
||||
Errors.ER_CLOSING_POOL,
|
||||
undefined,
|
||||
false
|
||||
);
|
||||
while ((task = taskQueue.shift())) {
|
||||
process.nextTick(task.reject, err);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.all(idleConnectionsEndings);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current active connections.
|
||||
* @return {number}
|
||||
*/
|
||||
this.activeConnections = function () {
|
||||
return Object.keys(activeConnections).length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current total connection number.
|
||||
* @return {number}
|
||||
*/
|
||||
this.totalConnections = function () {
|
||||
return this.activeConnections() + this.idleConnections();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current idle connection number.
|
||||
* @return {number}
|
||||
*/
|
||||
this.idleConnections = function () {
|
||||
return idleConnections.size();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current stacked connection request.
|
||||
* @return {number}
|
||||
*/
|
||||
this.taskQueueSize = function () {
|
||||
return taskQueue.size();
|
||||
};
|
||||
|
||||
/**
|
||||
* First connection creation.
|
||||
* activation is slightly different than pooling grow : If connection fails, there is many retries for 30s
|
||||
* (option initializationTimeout).
|
||||
* If connection fails, error will be thrown to request / console if no request, to ensure that error is thrown.
|
||||
*/
|
||||
this.initialize = function () {
|
||||
connectionInCreation = true;
|
||||
const self = this;
|
||||
const timeoutEnd = Date.now() + opts.initializationTimeout;
|
||||
connectionCreationLoop(self, 0, timeoutEnd)
|
||||
.then((conn) => {
|
||||
//add to pool
|
||||
if (closed) {
|
||||
conn.forceEnd().catch((err) => {});
|
||||
} else {
|
||||
addPoolConnection(self, conn);
|
||||
if (opts.idleTimeout > 0) {
|
||||
idleMaintainingTask = setInterval(idleMaintainer, 500, self);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
connectionInCreation = false;
|
||||
const task = taskQueue.shift();
|
||||
if (task) {
|
||||
firstTaskTimeout = clearTimeout(firstTaskTimeout);
|
||||
process.nextTick(task.reject, err);
|
||||
resetTimeoutToNextTask();
|
||||
} else if (!closed) {
|
||||
console.error(err);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
ensurePoolSize(self);
|
||||
});
|
||||
};
|
||||
|
||||
this.escape = (value) => {
|
||||
return Utils.escape(options.connOptions, searchInfo(), value);
|
||||
};
|
||||
|
||||
this.escapeId = (value) => {
|
||||
return Utils.escapeId(options.connOptions, searchInfo(), value);
|
||||
};
|
||||
|
||||
//*****************************************************************
|
||||
// internal methods
|
||||
//*****************************************************************
|
||||
|
||||
/**
|
||||
* Search info object of an existing connection. to know server type and version.
|
||||
* @returns information object if connection available.
|
||||
*/
|
||||
const searchInfo = () => {
|
||||
let info = null;
|
||||
let conn = idleConnections.get(0);
|
||||
|
||||
if (conn == null) {
|
||||
conn = Object.keys(activeConnections)[0];
|
||||
}
|
||||
|
||||
if (conn != null) {
|
||||
info = conn.info;
|
||||
}
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a connection from pool / execute query
|
||||
*
|
||||
* @param pool current pool
|
||||
* @param sql sql value (not mandatory)
|
||||
* @param values sql parameter (not mandatory)
|
||||
* @param isBatch is batch request
|
||||
* @return {*}
|
||||
*/
|
||||
const addRequest = function (pool, sql, values, isBatch) {
|
||||
if (closed) {
|
||||
return Promise.reject(
|
||||
Errors.createError(
|
||||
'pool is closed',
|
||||
false,
|
||||
null,
|
||||
'HY000',
|
||||
Errors.ER_POOL_ALREADY_CLOSED,
|
||||
undefined,
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return getIdleValidConnection(pool).then(
|
||||
(conn) => {
|
||||
pool.emit('acquire', conn);
|
||||
return processTask(conn, sql, values, isBatch);
|
||||
},
|
||||
() => {
|
||||
process.nextTick(() => pool.emit('enqueue'));
|
||||
|
||||
//no idle connection available
|
||||
//create a new connection if limit is not reached
|
||||
ensurePoolSize(pool);
|
||||
|
||||
//connections are all used, stack demand.
|
||||
return new Promise((resolve, reject) => {
|
||||
const task = {
|
||||
timeout: Date.now() + opts.acquireTimeout,
|
||||
reject: reject,
|
||||
resolve: resolve,
|
||||
sql: sql,
|
||||
values: values,
|
||||
isBatch: isBatch
|
||||
};
|
||||
if (!firstTaskTimeout) {
|
||||
firstTaskTimeout = setTimeout(rejectAndResetTimeout, opts.acquireTimeout, task);
|
||||
}
|
||||
taskQueue.push(task);
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an idle Connection.
|
||||
* If connection has not been used for some time ( minDelayValidation), validate connection status.
|
||||
*
|
||||
* @param pool pool
|
||||
* @returns {Promise<Connection|null>)} connection of null of no valid idle connection.
|
||||
*/
|
||||
const getIdleValidConnection = function (pool) {
|
||||
if (idleConnections.isEmpty()) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
const conn = idleConnections.shift();
|
||||
activeConnections[conn.threadId] = conn;
|
||||
if (opts.minDelayValidation <= 0 || Date.now() - conn.lastUse > opts.minDelayValidation) {
|
||||
return pingPromise(conn)
|
||||
.then(() => {
|
||||
initLeakProcess(conn);
|
||||
return Promise.resolve(conn);
|
||||
})
|
||||
.catch((err) => {
|
||||
delete activeConnections[conn.threadId];
|
||||
pool.emit('_remove-conn');
|
||||
return getIdleValidConnection(pool);
|
||||
});
|
||||
} else {
|
||||
//just check connection state
|
||||
if (conn.isValid()) {
|
||||
initLeakProcess(conn);
|
||||
return Promise.resolve(conn);
|
||||
} else {
|
||||
delete activeConnections[conn.threadId];
|
||||
pool.emit('_remove-conn');
|
||||
return getIdleValidConnection(pool);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Task request timeout handler
|
||||
* @param task
|
||||
*/
|
||||
const timeoutTask = (task) => {
|
||||
firstTaskTimeout = null;
|
||||
if (task === taskQueue.peekFront()) {
|
||||
taskQueue.shift();
|
||||
process.nextTick(
|
||||
task.reject,
|
||||
Errors.createError(
|
||||
'retrieve connection from pool timeout after ' +
|
||||
Math.abs(Date.now() - (task.timeout - opts.acquireTimeout)) +
|
||||
'ms',
|
||||
false,
|
||||
null,
|
||||
'HY000',
|
||||
Errors.ER_GET_CONNECTION_TIMEOUT,
|
||||
undefined,
|
||||
false
|
||||
)
|
||||
);
|
||||
} else {
|
||||
throw new Error('Rejection by timeout without task !!!');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reject task, and reset timeout to next waiting task if any.
|
||||
* @param task
|
||||
*/
|
||||
const rejectAndResetTimeout = (task) => {
|
||||
timeoutTask(task);
|
||||
resetTimeoutToNextTask();
|
||||
};
|
||||
|
||||
/**
|
||||
* Loop for connection creation.
|
||||
* This permits to wait before next try after a connection fail.
|
||||
*
|
||||
* @param pool current pool
|
||||
* @param iteration current iteration
|
||||
* @param timeoutEnd ending timeout
|
||||
* @returns {Promise<any>} Connection if found, error if not
|
||||
*/
|
||||
const connectionCreationLoop = function (pool, iteration, timeoutEnd) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const creationTryout = function (resolve, reject) {
|
||||
if (closed) {
|
||||
reject(
|
||||
Errors.createError(
|
||||
'Cannot create new connection to pool, pool closed',
|
||||
true,
|
||||
null,
|
||||
'08S01',
|
||||
Errors.ER_ADD_CONNECTION_CLOSED_POOL,
|
||||
null
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
iteration++;
|
||||
createConnectionPool(pool)
|
||||
.then((conn) => {
|
||||
resolve(conn);
|
||||
})
|
||||
.catch((err) => {
|
||||
//if timeout is reached or authentication fail return error
|
||||
if (
|
||||
closed ||
|
||||
(err.errno && (err.errno === 1524 || err.errno === 1045 || err.errno === 1698)) ||
|
||||
timeoutEnd < Date.now()
|
||||
) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(creationTryout.bind(null, resolve, reject), 500);
|
||||
});
|
||||
};
|
||||
//initial without timeout
|
||||
creationTryout(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
const addPoolConnection = function (pool, conn) {
|
||||
conn.lastUse = Date.now();
|
||||
const initialDestroyFct = conn.destroy;
|
||||
conn.destroy = () => {
|
||||
removeLeakProcess(conn);
|
||||
delete activeConnections[conn.threadId];
|
||||
initialDestroyFct();
|
||||
pool.emit('_remove-conn');
|
||||
};
|
||||
|
||||
//Connection error
|
||||
// -> evict connection from pool
|
||||
conn.on('error', (err) => {
|
||||
let idx = 0;
|
||||
let currConn;
|
||||
removeLeakProcess(conn);
|
||||
delete activeConnections[conn.threadId];
|
||||
while ((currConn = idleConnections.peekAt(idx))) {
|
||||
if (currConn === conn) {
|
||||
idleConnections.removeOne(idx);
|
||||
break;
|
||||
} else {
|
||||
//since connection did have an error, other waiting connection might too
|
||||
//forcing validation when borrowed next time, even if "minDelayValidation" is not reached.
|
||||
currConn.lastUse = Math.min(Date.now() - opts.minDelayValidation, currConn.lastUse);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
pool.emit('_remove-conn');
|
||||
});
|
||||
connectionInCreation = false;
|
||||
idleConnections.push(conn);
|
||||
pool.emit('_idle-conn');
|
||||
process.nextTick(() => pool.emit('connection', conn));
|
||||
};
|
||||
|
||||
this._releaseConnection = function (conn) {
|
||||
removeLeakProcess(conn);
|
||||
conn.lastUse = Date.now();
|
||||
delete activeConnections[conn.threadId];
|
||||
const pool = this;
|
||||
if (closed) {
|
||||
return conn.forceEnd().catch(() => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
} else if (conn.isValid()) {
|
||||
pool.emit('release', conn);
|
||||
idleConnections.push(conn);
|
||||
process.nextTick(() => pool.emit('_idle-conn'));
|
||||
} else {
|
||||
ensurePoolSize(pool);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Grow pool connections until reaching connection limit.
|
||||
*/
|
||||
const ensurePoolSize = function (pool) {
|
||||
if (
|
||||
!connectionInCreation &&
|
||||
pool.idleConnections() < opts.minimumIdle &&
|
||||
pool.totalConnections() < opts.connectionLimit &&
|
||||
!closed
|
||||
) {
|
||||
connectionInCreation = true;
|
||||
process.nextTick(() => {
|
||||
const timeoutEnd = Date.now() + opts.initializationTimeout;
|
||||
if (!closed) {
|
||||
connectionCreationLoop(pool, 0, timeoutEnd)
|
||||
.then((conn) => {
|
||||
if (closed) {
|
||||
return conn.forceEnd().catch((err) => {});
|
||||
}
|
||||
addPoolConnection(pool, conn);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (pool.totalConnections() === 0) {
|
||||
const task = taskQueue.shift();
|
||||
if (task) {
|
||||
firstTaskTimeout = clearTimeout(firstTaskTimeout);
|
||||
process.nextTick(task.reject, err);
|
||||
resetTimeoutToNextTask();
|
||||
}
|
||||
} else if (!closed) {
|
||||
console.error(`pool fail to create connection (${err.message})`);
|
||||
}
|
||||
|
||||
//delay next try
|
||||
setTimeout(() => {
|
||||
connectionInCreation = false;
|
||||
if (taskQueue.size() > 0) {
|
||||
ensurePoolSize(pool);
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const resetTimeoutToNextTask = () => {
|
||||
//handle next Timer
|
||||
const currTime = Date.now();
|
||||
let nextTask;
|
||||
while ((nextTask = taskQueue.peekFront())) {
|
||||
if (nextTask.timeout < currTime) {
|
||||
timeoutTask(nextTask);
|
||||
} else {
|
||||
firstTaskTimeout = setTimeout(rejectAndResetTimeout, nextTask.timeout - currTime, nextTask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Permit to remove idle connection if unused for some time.
|
||||
* @param pool current pool
|
||||
*/
|
||||
const idleMaintainer = function (pool) {
|
||||
let toRemove = Math.max(1, pool.idleConnections() - opts.minimumIdle);
|
||||
while (toRemove > 0) {
|
||||
const conn = idleConnections.peek();
|
||||
--toRemove;
|
||||
if (conn && conn.lastUse + opts.idleTimeout * 1000 < Date.now()) {
|
||||
idleConnections.shift();
|
||||
conn.forceEnd().catch((err) => {});
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ensurePoolSize(pool);
|
||||
};
|
||||
|
||||
this._discardConnection = (conn) => {
|
||||
removeLeakProcess(conn);
|
||||
delete activeConnections[conn.threadId];
|
||||
conn.forceEnd().catch((err) => {});
|
||||
this.emit('_remove-conn');
|
||||
};
|
||||
|
||||
const logLeak = (conn) => {
|
||||
console.log(
|
||||
'Possible connection leak on thread ' +
|
||||
conn.info.threadId +
|
||||
' (connection not returned to pool since ' +
|
||||
(Date.now() - conn.lastUse) +
|
||||
'ms. Did connection.released() been implemented'
|
||||
);
|
||||
conn.leaked = true;
|
||||
};
|
||||
|
||||
const _initLeakProcess = (conn) => {
|
||||
conn.lastUse = Date.now();
|
||||
conn.leaked = false;
|
||||
conn.leakProcess = setTimeout(logLeak, opts.leakDetectionTimeout, conn);
|
||||
};
|
||||
|
||||
const _removeLeakProcess = (conn) => {
|
||||
conn.leakProcess = clearTimeout(conn.leakProcess);
|
||||
if (conn.leaked) {
|
||||
console.log(
|
||||
'Previous possible leak connection with thread ' +
|
||||
conn.info.threadId +
|
||||
' was returned to pool'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch next waiting task request if available connections.
|
||||
*/
|
||||
const handleTaskQueue = function () {
|
||||
firstTaskTimeout = clearTimeout(firstTaskTimeout);
|
||||
const task = taskQueue.shift();
|
||||
|
||||
if (task) {
|
||||
const conn = idleConnections.shift();
|
||||
if (conn) {
|
||||
initLeakProcess(conn);
|
||||
this.emit('acquire', conn);
|
||||
activeConnections[conn.threadId] = conn;
|
||||
resetTimeoutToNextTask();
|
||||
processTask(conn, task.sql, task.values, task.isBatch)
|
||||
.then(task.resolve)
|
||||
.catch(task.reject);
|
||||
} else {
|
||||
taskQueue.unshift(task);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const opts = options;
|
||||
let closed = false;
|
||||
let connectionInCreation = false;
|
||||
const initLeakProcess = opts.leakDetectionTimeout > 0 ? _initLeakProcess : () => {};
|
||||
const removeLeakProcess = opts.leakDetectionTimeout > 0 ? _removeLeakProcess : () => {};
|
||||
const idleConnections = new Queue();
|
||||
const activeConnections = {};
|
||||
const taskQueue = new Queue();
|
||||
let idleMaintainingTask;
|
||||
let firstTaskTimeout;
|
||||
Object.defineProperty(this, 'closed', {
|
||||
get() {
|
||||
return closed;
|
||||
}
|
||||
});
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.on('_idle-conn', handleTaskQueue.bind(this));
|
||||
this.on('_remove-conn', ensurePoolSize.bind(this, this));
|
||||
this.on('connection', ensurePoolSize.bind(this, this));
|
||||
}
|
||||
|
||||
util.inherits(PoolBase, EventEmitter);
|
||||
module.exports = PoolBase;
|
||||
201
node_modules/mariadb/lib/pool-callback.js
generated
vendored
Normal file
201
node_modules/mariadb/lib/pool-callback.js
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
'use strict';
|
||||
|
||||
const PoolBase = require('./pool-base');
|
||||
const ConnectionCallback = require('./connection-callback');
|
||||
const Errors = require('./misc/errors');
|
||||
const util = require('util');
|
||||
|
||||
function PoolCallback(options) {
|
||||
const processTaskCallback = function (conn, sql, values, isBatch) {
|
||||
if (sql) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fct = isBatch ? conn.batch : conn.query;
|
||||
fct(sql, values, (err, rows, fields) => {
|
||||
conn.releaseWithoutError();
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
return resolve(rows);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve(conn);
|
||||
}
|
||||
};
|
||||
|
||||
const pingPromise = function (conn) {
|
||||
return new Promise((resolve, reject) => {
|
||||
conn.ping(options.pingTimeout, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const createConnectionPoolCallback = function (pool) {
|
||||
const conn = new ConnectionCallback(options.connOptions);
|
||||
return new Promise(function (resolve, reject) {
|
||||
conn.connect((err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
if (pool.closed) {
|
||||
//discard connection
|
||||
conn.end((err) => {});
|
||||
reject(
|
||||
Errors.createError(
|
||||
'Cannot create new connection to pool, pool closed',
|
||||
true,
|
||||
null,
|
||||
'08S01',
|
||||
Errors.ER_ADD_CONNECTION_CLOSED_POOL,
|
||||
null
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const initialEnd = conn.end;
|
||||
conn.forceEnd = () => {
|
||||
return new Promise(function (res, rej) {
|
||||
initialEnd((err) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
} else {
|
||||
res();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
conn.release = function (cb) {
|
||||
if (pool.closed) {
|
||||
pool._discardConnection(conn);
|
||||
if (cb) cb();
|
||||
return;
|
||||
}
|
||||
if (options.noControlAfterUse) {
|
||||
pool._releaseConnection(conn);
|
||||
if (cb) cb();
|
||||
return;
|
||||
}
|
||||
|
||||
//if server permit it, reset the connection, or rollback only if not
|
||||
// COM_RESET_CONNECTION exist since mysql 5.7.3 and mariadb 10.2.4
|
||||
// but not possible to use it with mysql waiting for https://bugs.mysql.com/bug.php?id=97633 correction.
|
||||
// and mariadb only since https://jira.mariadb.org/browse/MDEV-18281
|
||||
let revertFunction = conn.rollback;
|
||||
if (
|
||||
options.resetAfterUse &&
|
||||
conn.info.isMariaDB() &&
|
||||
((conn.info.serverVersion.minor === 2 && conn.info.hasMinVersion(10, 2, 22)) ||
|
||||
conn.info.hasMinVersion(10, 3, 13))
|
||||
) {
|
||||
revertFunction = conn.reset;
|
||||
}
|
||||
revertFunction((errCall) => {
|
||||
if (errCall) {
|
||||
//uncertain connection state.
|
||||
pool._discardConnection(conn);
|
||||
if (cb) cb();
|
||||
return;
|
||||
} else {
|
||||
pool._releaseConnection(conn);
|
||||
}
|
||||
if (cb) cb();
|
||||
});
|
||||
};
|
||||
conn.end = conn.release;
|
||||
conn.releaseWithoutError = () => {
|
||||
conn.end((err) => {});
|
||||
};
|
||||
resolve(conn);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
PoolBase.call(this, options, processTaskCallback, createConnectionPoolCallback, pingPromise);
|
||||
|
||||
const getConnectionPromise = this.getConnection.bind(this);
|
||||
const endPromise = this.end.bind(this);
|
||||
const queryPromise = this.query.bind(this);
|
||||
const batchPromise = this.batch.bind(this);
|
||||
const emptyError = (err) => {};
|
||||
|
||||
//*****************************************************************
|
||||
// internal equivalent with callback of promised functions
|
||||
//*****************************************************************
|
||||
|
||||
const _getConnectionCallback = (callback) => {
|
||||
getConnectionPromise()
|
||||
.then((conn) => {
|
||||
if (callback) callback(null, conn);
|
||||
})
|
||||
.catch(callback || emptyError);
|
||||
};
|
||||
|
||||
const _endCallback = (callback) => {
|
||||
endPromise()
|
||||
.then(() => {
|
||||
if (callback) callback(null);
|
||||
})
|
||||
.catch(callback || emptyError);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute query using text protocol with callback emit columns/data/end/error
|
||||
* events to permit streaming big result-set
|
||||
*
|
||||
* @param sql sql parameter Object can be used to supersede default option.
|
||||
* Object must then have sql property.
|
||||
* @param values object / array of placeholder values (not mandatory)
|
||||
* @param cb callback
|
||||
* @returns {Query} query
|
||||
*/
|
||||
const _queryCallback = function (sql, values, cb) {
|
||||
let _cb = cb,
|
||||
_values = values;
|
||||
|
||||
if (typeof values === 'function') {
|
||||
_cb = values;
|
||||
_values = undefined;
|
||||
}
|
||||
|
||||
queryPromise(sql, _values)
|
||||
.then((rows) => {
|
||||
if (_cb) _cb(null, rows, rows.meta);
|
||||
})
|
||||
.catch(_cb || emptyError);
|
||||
};
|
||||
|
||||
const _batchCallback = function (sql, values, cb) {
|
||||
let _values = values,
|
||||
_cb = cb;
|
||||
|
||||
if (typeof values === 'function') {
|
||||
_cb = values;
|
||||
_values = undefined;
|
||||
}
|
||||
|
||||
batchPromise(sql, _values)
|
||||
.then((rows) => {
|
||||
if (_cb) _cb(null, rows, rows.meta);
|
||||
})
|
||||
.catch(_cb || emptyError);
|
||||
};
|
||||
|
||||
//*****************************************************************
|
||||
// replacing public promise function with callback equivalent
|
||||
//*****************************************************************
|
||||
|
||||
this.end = _endCallback;
|
||||
this.query = _queryCallback;
|
||||
this.batch = _batchCallback;
|
||||
this.getConnection = _getConnectionCallback;
|
||||
}
|
||||
|
||||
util.inherits(PoolCallback, PoolBase);
|
||||
|
||||
module.exports = PoolCallback;
|
||||
66
node_modules/mariadb/lib/pool-cluster-callback.js
generated
vendored
Normal file
66
node_modules/mariadb/lib/pool-cluster-callback.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
|
||||
const PoolCluster = require('./pool-cluster');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Create a new Cluster.
|
||||
* Cluster handle pools with patterns and handle failover / distributed load
|
||||
* according to selectors (round robin / random / ordered )
|
||||
*
|
||||
* @param args cluster argurments. see pool-cluster-options.
|
||||
* @constructor
|
||||
*/
|
||||
function PoolClusterCallback(args) {
|
||||
PoolCluster.call(this, args);
|
||||
this.setCallback();
|
||||
|
||||
const initialGetConnection = this.getConnection.bind(this);
|
||||
const initialEnd = this.end.bind(this);
|
||||
|
||||
/**
|
||||
* End cluster (and underlying pools).
|
||||
*
|
||||
* @param callback - not mandatory
|
||||
*/
|
||||
this.end = (callback) => {
|
||||
if (callback && typeof callback !== 'function') {
|
||||
throw new Error('callback parameter must be a function');
|
||||
}
|
||||
const endingFct = callback ? callback : () => {};
|
||||
|
||||
initialEnd()
|
||||
.then(() => {
|
||||
endingFct();
|
||||
})
|
||||
.catch(endingFct);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get connection from available pools matching pattern, according to selector
|
||||
*
|
||||
* @param pattern pattern filter (not mandatory)
|
||||
* @param selector node selector ('RR','RANDOM' or 'ORDER')
|
||||
* @param callback callback function
|
||||
*/
|
||||
this.getConnection = (pattern, selector, callback) => {
|
||||
let pat = pattern,
|
||||
sel = selector,
|
||||
cal = callback;
|
||||
if (typeof pattern === 'function') {
|
||||
pat = null;
|
||||
sel = null;
|
||||
cal = pattern;
|
||||
} else if (typeof selector === 'function') {
|
||||
sel = null;
|
||||
cal = selector;
|
||||
}
|
||||
const endingFct = cal ? cal : (conn) => {};
|
||||
|
||||
initialGetConnection(pat, sel, endingFct);
|
||||
};
|
||||
}
|
||||
|
||||
util.inherits(PoolClusterCallback, PoolCluster);
|
||||
|
||||
module.exports = PoolClusterCallback;
|
||||
407
node_modules/mariadb/lib/pool-cluster.js
generated
vendored
Normal file
407
node_modules/mariadb/lib/pool-cluster.js
generated
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
'use strict';
|
||||
|
||||
const PoolClusterOptions = require('./config/pool-cluster-options');
|
||||
const PoolOptions = require('./config/pool-options');
|
||||
const Pool = require('./pool-promise');
|
||||
const PoolCallback = require('./pool-callback');
|
||||
const FilteredPoolCluster = require('./filtered-pool-cluster');
|
||||
const EventEmitter = require('events');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Create a new Cluster.
|
||||
* Cluster handle pools with patterns and handle failover / distributed load
|
||||
* according to selectors (round robin / random / ordered )
|
||||
*
|
||||
* @param args cluster argurments. see pool-cluster-options.
|
||||
* @constructor
|
||||
*/
|
||||
function PoolCluster(args) {
|
||||
const opts = new PoolClusterOptions(args);
|
||||
const nodes = {};
|
||||
let cachedPatterns = {};
|
||||
let nodeCounter = 0;
|
||||
EventEmitter.call(this);
|
||||
|
||||
/**
|
||||
* Add a new pool node to cluster.
|
||||
*
|
||||
* @param id identifier
|
||||
* @param config pool configuration
|
||||
*/
|
||||
this.add = (id, config) => {
|
||||
let identifier;
|
||||
if (typeof id === 'string' || id instanceof String) {
|
||||
identifier = id;
|
||||
if (nodes[identifier])
|
||||
throw new Error("Node identifier '" + identifier + "' already exist !");
|
||||
} else {
|
||||
identifier = 'PoolNode-' + nodeCounter++;
|
||||
config = id;
|
||||
}
|
||||
const options = new PoolOptions(config);
|
||||
const pool = _createPool(options);
|
||||
pool.initialize();
|
||||
nodes[identifier] = pool;
|
||||
};
|
||||
|
||||
/**
|
||||
* End cluster (and underlying pools).
|
||||
*
|
||||
* @return {Promise<any[]>}
|
||||
*/
|
||||
this.end = () => {
|
||||
cachedPatterns = {};
|
||||
const poolEndPromise = [];
|
||||
Object.keys(nodes).forEach((pool) => {
|
||||
poolEndPromise.push(nodes[pool].end());
|
||||
delete nodes[pool];
|
||||
});
|
||||
|
||||
return Promise.all(poolEndPromise);
|
||||
};
|
||||
|
||||
this.of = (pattern, selector) => {
|
||||
return new FilteredPoolCluster(this, pattern, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove nodes according to pattern.
|
||||
*
|
||||
* @param pattern pattern
|
||||
*/
|
||||
this.remove = (pattern) => {
|
||||
if (!pattern) throw new Error('pattern parameter in Cluster.remove(pattern) is mandatory');
|
||||
|
||||
const regex = RegExp(pattern);
|
||||
Object.keys(nodes).forEach((key) => {
|
||||
if (regex.test(key)) {
|
||||
nodes[key].end();
|
||||
delete nodes[key];
|
||||
cachedPatterns = {};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get connection from available pools matching pattern, according to selector
|
||||
*
|
||||
* @param pattern pattern filter (not mandatory)
|
||||
* @param selector node selector ('RR','RANDOM' or 'ORDER')
|
||||
* @return {Promise}
|
||||
*/
|
||||
this.getConnection = (pattern, selector) => {
|
||||
return _getConnection(this, pattern, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Force using callback methods.
|
||||
*/
|
||||
this.setCallback = () => {
|
||||
this.getConnection = _getConnectionCallback.bind(this, this);
|
||||
_createPool = _createPoolCallback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get connection from available pools matching pattern, according to selector
|
||||
* with additional parameter to avoid reusing failing node
|
||||
*
|
||||
* @param pattern pattern filter (not mandatory)
|
||||
* @param selector node selector ('RR','RANDOM' or 'ORDER')
|
||||
* @param avoidNodeKey failing node
|
||||
* @param lastError last error
|
||||
* @return {Promise}
|
||||
* @private
|
||||
*/
|
||||
const _getConnection = (cluster, pattern, selector, avoidNodeKey, lastError) => {
|
||||
const matchingNodeList = _matchingNodes(pattern || /^/);
|
||||
|
||||
if (matchingNodeList.length === 0) {
|
||||
if (Object.keys(nodes).length === 0 && !lastError) {
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
'No node have been added to cluster ' +
|
||||
'or nodes have been removed due to too much connection error'
|
||||
)
|
||||
);
|
||||
}
|
||||
if (avoidNodeKey === undefined)
|
||||
return Promise.reject(new Error("No node found for pattern '" + pattern + "'"));
|
||||
const errMsg =
|
||||
"No Connection available for '" +
|
||||
pattern +
|
||||
"'" +
|
||||
(lastError ? '. Last connection error was: ' + lastError.message : '');
|
||||
return Promise.reject(new Error(errMsg));
|
||||
}
|
||||
|
||||
const retry = _getConnection.bind(this, this, pattern, selector);
|
||||
try {
|
||||
const nodeKey = _selectPool(matchingNodeList, selector, avoidNodeKey);
|
||||
return _handleConnectionError(cluster, matchingNodeList, nodeKey, retry);
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
};
|
||||
|
||||
let _createPool = (options) => {
|
||||
return new Pool(options, false);
|
||||
};
|
||||
|
||||
const _createPoolCallback = (options) => {
|
||||
return new PoolCallback(options, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get connection from available pools matching pattern, according to selector
|
||||
* with additional parameter to avoid reusing failing node
|
||||
*
|
||||
* @param pattern pattern filter (not mandatory)
|
||||
* @param selector node selector ('RR','RANDOM' or 'ORDER')
|
||||
* @param callback callback function
|
||||
* @param avoidNodeKey failing node
|
||||
* @param lastError last error
|
||||
* @private
|
||||
*/
|
||||
const _getConnectionCallback = (
|
||||
cluster,
|
||||
pattern,
|
||||
selector,
|
||||
callback,
|
||||
avoidNodeKey,
|
||||
lastError
|
||||
) => {
|
||||
const matchingNodeList = _matchingNodes(pattern || /^/);
|
||||
|
||||
if (matchingNodeList.length === 0) {
|
||||
if (Object.keys(nodes).length === 0 && !lastError) {
|
||||
callback(
|
||||
new Error(
|
||||
'No node have been added to cluster ' +
|
||||
'or nodes have been removed due to too much connection error'
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (avoidNodeKey === undefined)
|
||||
callback(new Error("No node found for pattern '" + pattern + "'"));
|
||||
const errMsg =
|
||||
"No Connection available for '" +
|
||||
pattern +
|
||||
"'" +
|
||||
(lastError ? '. Last connection error was: ' + lastError.message : '');
|
||||
callback(new Error(errMsg));
|
||||
return;
|
||||
}
|
||||
|
||||
const retry = _getConnectionCallback.bind(this, this, pattern, selector, callback);
|
||||
try {
|
||||
const nodeKey = _selectPool(matchingNodeList, selector, avoidNodeKey);
|
||||
_handleConnectionCallbackError(this, matchingNodeList, nodeKey, retry, callback);
|
||||
} catch (e) {
|
||||
callback(e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Selecting nodes according to pattern.
|
||||
*
|
||||
* @param pattern pattern
|
||||
* @return {*}
|
||||
* @private
|
||||
*/
|
||||
const _matchingNodes = (pattern) => {
|
||||
if (cachedPatterns[pattern]) return cachedPatterns[pattern];
|
||||
|
||||
const regex = RegExp(pattern);
|
||||
const matchingNodeList = [];
|
||||
Object.keys(nodes).forEach((key) => {
|
||||
if (regex.test(key)) {
|
||||
matchingNodeList.push(key);
|
||||
}
|
||||
});
|
||||
|
||||
cachedPatterns[pattern] = matchingNodeList;
|
||||
return matchingNodeList;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select next node to be chosen in nodeList according to selector and failed nodes.
|
||||
*
|
||||
* @param nodeList current node list
|
||||
* @param selectorParam selector
|
||||
* @param avoidNodeKey last failing node to avoid selecting this one.
|
||||
* @return {Promise}
|
||||
* @private
|
||||
*/
|
||||
const _selectPool = (nodeList, selectorParam, avoidNodeKey) => {
|
||||
const selector = selectorParam || opts.defaultSelector;
|
||||
let retry = 0;
|
||||
let selectorFct;
|
||||
let nodeKey;
|
||||
switch (selector) {
|
||||
case 'RR':
|
||||
selectorFct = roundRobinSelector;
|
||||
break;
|
||||
|
||||
case 'RANDOM':
|
||||
selectorFct = randomSelector;
|
||||
break;
|
||||
|
||||
case 'ORDER':
|
||||
selectorFct = orderedSelector;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(
|
||||
"Wrong selector value '" + selector + "'. Possible values are 'RR','RANDOM' or 'ORDER'"
|
||||
);
|
||||
}
|
||||
|
||||
nodeKey = selectorFct(nodeList, retry);
|
||||
while (
|
||||
(avoidNodeKey === nodeKey || nodes[nodeKey].blacklistedUntil > Date.now()) &&
|
||||
retry < nodeList.length - 1
|
||||
) {
|
||||
retry++;
|
||||
nodeKey = selectorFct(nodeList, retry);
|
||||
}
|
||||
return nodeKey;
|
||||
};
|
||||
|
||||
/**
|
||||
* Round robin selector: using nodes one after the other.
|
||||
*
|
||||
* @param nodeList node list
|
||||
* @return {String}
|
||||
*/
|
||||
const roundRobinSelector = (nodeList) => {
|
||||
let lastRoundRobin = nodeList.lastRrIdx;
|
||||
if (lastRoundRobin === undefined) lastRoundRobin = -1;
|
||||
if (++lastRoundRobin >= nodeList.length) lastRoundRobin = 0;
|
||||
nodeList.lastRrIdx = lastRoundRobin;
|
||||
return nodeList[lastRoundRobin];
|
||||
};
|
||||
|
||||
/**
|
||||
* Random selector: use a random node.
|
||||
*
|
||||
* @param nodeList node list
|
||||
* @return {String}
|
||||
*/
|
||||
const randomSelector = (nodeList) => {
|
||||
let randomIdx = Math.floor(Math.random() * nodeList.length);
|
||||
return nodeList[randomIdx];
|
||||
};
|
||||
|
||||
/**
|
||||
* Ordered selector: always use the nodes in sequence, unless failing.
|
||||
*
|
||||
* @param nodeList node list
|
||||
* @param retry sequence number if last node is tagged has failing
|
||||
* @return {String}
|
||||
*/
|
||||
const orderedSelector = (nodeList, retry) => {
|
||||
return nodeList[retry];
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect, or if fail handle retry / set timeout error
|
||||
*
|
||||
* @param cluster current cluster
|
||||
* @param nodeList current node list
|
||||
* @param nodeKey node name to connect
|
||||
* @param retryFct retry function
|
||||
* @return {Promise}
|
||||
* @private
|
||||
*/
|
||||
const _handleConnectionError = (cluster, nodeList, nodeKey, retryFct) => {
|
||||
const node = nodes[nodeKey];
|
||||
return node
|
||||
.getConnection()
|
||||
.then((conn) => {
|
||||
node.errorCount = 0;
|
||||
return Promise.resolve(conn);
|
||||
})
|
||||
.catch((err) => {
|
||||
node.errorCount = node.errorCount ? node.errorCount + 1 : 1;
|
||||
node.blacklistedUntil = Date.now() + opts.restoreNodeTimeout;
|
||||
if (
|
||||
opts.removeNodeErrorCount &&
|
||||
node.errorCount >= opts.removeNodeErrorCount &&
|
||||
nodes[nodeKey]
|
||||
) {
|
||||
delete nodes[nodeKey];
|
||||
cachedPatterns = {};
|
||||
delete nodeList.lastRrIdx;
|
||||
process.nextTick(() => cluster.emit('remove', nodeKey));
|
||||
//remove node from configuration if not already removed
|
||||
node.end().catch((err) => {
|
||||
// dismiss error
|
||||
});
|
||||
}
|
||||
|
||||
if (nodeList.length !== 0 && opts.canRetry) {
|
||||
return retryFct(nodeKey, err);
|
||||
}
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect, or if fail handle retry / set timeout error
|
||||
*
|
||||
* @param cluster current cluster
|
||||
* @param nodeList current node list
|
||||
* @param nodeKey node name to connect
|
||||
* @param retryFct retry function
|
||||
* @param callback callback function
|
||||
* @private
|
||||
*/
|
||||
const _handleConnectionCallbackError = (cluster, nodeList, nodeKey, retryFct, callback) => {
|
||||
const node = nodes[nodeKey];
|
||||
node.getConnection((err, conn) => {
|
||||
if (err) {
|
||||
node.errorCount = node.errorCount ? node.errorCount + 1 : 1;
|
||||
node.blacklistedUntil = Date.now() + opts.restoreNodeTimeout;
|
||||
if (
|
||||
opts.removeNodeErrorCount &&
|
||||
node.errorCount >= opts.removeNodeErrorCount &&
|
||||
nodes[nodeKey]
|
||||
) {
|
||||
delete nodes[nodeKey];
|
||||
cachedPatterns = {};
|
||||
delete nodeList.lastRrIdx;
|
||||
process.nextTick(() => cluster.emit('remove', nodeKey));
|
||||
//remove node from configuration if not already removed
|
||||
node.end(() => {
|
||||
//dismiss error
|
||||
});
|
||||
if (nodeList.length === 0) return Promise.reject(err);
|
||||
}
|
||||
|
||||
if (opts.canRetry) return retryFct(nodeKey, err);
|
||||
callback(err);
|
||||
} else {
|
||||
node.errorCount = 0;
|
||||
callback(null, conn);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//*****************************************************************
|
||||
// internal public testing methods
|
||||
//*****************************************************************
|
||||
|
||||
function TestMethods() {}
|
||||
TestMethods.prototype.getNodes = () => {
|
||||
return nodes;
|
||||
};
|
||||
|
||||
this.__tests = new TestMethods();
|
||||
}
|
||||
|
||||
util.inherits(PoolCluster, EventEmitter);
|
||||
|
||||
module.exports = PoolCluster;
|
||||
107
node_modules/mariadb/lib/pool-promise.js
generated
vendored
Normal file
107
node_modules/mariadb/lib/pool-promise.js
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
'use strict';
|
||||
|
||||
const Connection = require('./connection');
|
||||
const PoolBase = require('./pool-base');
|
||||
const Errors = require('./misc/errors');
|
||||
const util = require('util');
|
||||
|
||||
function PoolPromise(options) {
|
||||
const processTaskPromise = function (conn, sql, values, isBatch) {
|
||||
if (sql) {
|
||||
const fct = isBatch ? conn.batch : conn.query;
|
||||
return fct(sql, values)
|
||||
.then((res) => {
|
||||
conn.releaseWithoutError();
|
||||
return Promise.resolve(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
conn.releaseWithoutError();
|
||||
return Promise.reject(err);
|
||||
});
|
||||
}
|
||||
return Promise.resolve(conn);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add connection to pool.
|
||||
*/
|
||||
const createConnectionPoolPromise = function (pool) {
|
||||
const conn = new Connection(options.connOptions);
|
||||
return conn
|
||||
.connect()
|
||||
.then(() => {
|
||||
if (pool.closed) {
|
||||
conn
|
||||
.end()
|
||||
.then(() => {})
|
||||
.catch(() => {});
|
||||
return Promise.reject(
|
||||
Errors.createError(
|
||||
'Cannot create new connection to pool, pool closed',
|
||||
true,
|
||||
null,
|
||||
'08S01',
|
||||
Errors.ER_ADD_CONNECTION_CLOSED_POOL,
|
||||
null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
conn.releaseWithoutError = () => {
|
||||
conn.release().catch(() => {});
|
||||
};
|
||||
|
||||
conn.forceEnd = conn.end;
|
||||
|
||||
conn.release = () => {
|
||||
if (pool.closed) {
|
||||
pool._discardConnection(conn);
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (options.noControlAfterUse) {
|
||||
pool._releaseConnection(conn);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
//if server permit it, reset the connection, or rollback only if not
|
||||
// COM_RESET_CONNECTION exist since mysql 5.7.3 and mariadb 10.2.4
|
||||
// but not possible to use it with mysql waiting for https://bugs.mysql.com/bug.php?id=97633 correction.
|
||||
// and mariadb only since https://jira.mariadb.org/browse/MDEV-18281
|
||||
let revertFunction = conn.rollback;
|
||||
if (
|
||||
options.resetAfterUse &&
|
||||
conn.info.isMariaDB() &&
|
||||
((conn.info.serverVersion.minor === 2 && conn.info.hasMinVersion(10, 2, 22)) ||
|
||||
conn.info.hasMinVersion(10, 3, 13))
|
||||
) {
|
||||
revertFunction = conn.reset;
|
||||
}
|
||||
|
||||
return revertFunction()
|
||||
.then(() => {
|
||||
pool._releaseConnection(conn);
|
||||
return Promise.resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
//uncertain connection state.
|
||||
// discard it
|
||||
pool._discardConnection(conn);
|
||||
return Promise.resolve();
|
||||
});
|
||||
};
|
||||
conn.end = conn.release;
|
||||
return Promise.resolve(conn);
|
||||
})
|
||||
.catch((err) => {
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
|
||||
PoolBase.call(this, options, processTaskPromise, createConnectionPoolPromise, (conn) =>
|
||||
conn.ping(options.pingTimeout)
|
||||
);
|
||||
}
|
||||
|
||||
util.inherits(PoolPromise, PoolBase);
|
||||
|
||||
module.exports = PoolPromise;
|
||||
Reference in New Issue
Block a user