Comparing version 2.3.3 to 3.0.0-rc.1
import { | ||
Connection as PromiseConnection, | ||
Pool as PromisePool, | ||
PoolConnection as PromisePoolConnection | ||
PoolConnection as PromisePoolConnection, | ||
} from './promise'; | ||
@@ -75,2 +75,11 @@ | ||
promise(promiseImpl?: PromiseConstructor): PromiseConnection; | ||
unprepare(sql: string): mysql.PrepareStatementInfo; | ||
prepare(sql: string, callback?: (err: mysql.QueryError | null, statement: mysql.PrepareStatementInfo) => any): mysql.Prepare; | ||
serverHandshake(args: any): any; | ||
writeOk(args?: mysql.OkPacketParams): void; | ||
writeError(args?: mysql.ErrorPacketParams): void; | ||
writeEof(warnings?: number, statusFlags?: number): void; | ||
writeTextResult(rows?: Array<any>, columns?: Array<any>): void; | ||
writePacket(packet: any): void; | ||
sequenceId: number; | ||
} | ||
@@ -153,2 +162,6 @@ | ||
promise(promiseImpl?: PromiseConstructor): PromisePool; | ||
unprepare(sql: string): mysql.PrepareStatementInfo; | ||
prepare(sql: string, callback?: (err: mysql.QueryError | null, statement: mysql.PrepareStatementInfo) => any): mysql.Prepare; | ||
config: mysql.PoolOptions; | ||
} | ||
@@ -187,2 +200,10 @@ | ||
export interface ConnectionConfig extends ConnectionOptions { | ||
mergeFlags(defaultFlags: string[], userFlags: string[] | string): number; | ||
getDefaultFlags(options?: ConnectionOptions): string[]; | ||
getCharsetNumber(charset: string): number; | ||
getSSLProfile(name: string): { ca: string[] }; | ||
parseUrl(url: string): { host: string, port: number, database: string, user: string, password: string, [key: string]: any }; | ||
} | ||
export interface PoolOptions extends mysql.PoolOptions, ConnectionOptions {} | ||
@@ -189,0 +210,0 @@ |
@@ -15,2 +15,3 @@ 'use strict'; | ||
exports.Connection = Connection; | ||
exports.ConnectionConfig = ConnectionConfig; | ||
@@ -17,0 +18,0 @@ const Pool = require('./lib/pool.js'); |
@@ -5,3 +5,3 @@ 'use strict'; | ||
const crypto = require('crypto'); | ||
const { xor } = require('../auth_41'); | ||
const { xorRotating } = require('../auth_41'); | ||
@@ -15,3 +15,3 @@ const REQUEST_SERVER_KEY_PACKET = Buffer.from([1]); | ||
function encrypt(password, scramble, key) { | ||
const stage1 = xor( | ||
const stage1 = xorRotating( | ||
Buffer.from(`${password}\0`, 'utf8').toString('binary'), | ||
@@ -18,0 +18,0 @@ scramble.toString('binary') |
@@ -12,2 +12,3 @@ // This file was modified by Oracle on July 5, 2021. | ||
const mysql_native_password = require('../auth_plugins/mysql_native_password.js'); | ||
const mysql_clear_password = require('../auth_plugins/mysql_clear_password.js'); | ||
@@ -17,3 +18,4 @@ const standardAuthPlugins = { | ||
caching_sha2_password: caching_sha2_password({}), | ||
mysql_native_password: mysql_native_password({}) | ||
mysql_native_password: mysql_native_password({}), | ||
mysql_clear_password: mysql_clear_password({}) | ||
}; | ||
@@ -20,0 +22,0 @@ |
@@ -0,1 +1,7 @@ | ||
// This file was modified by Oracle on September 21, 2021. | ||
// The changes involve saving additional authentication factor passwords | ||
// in the command scope and enabling multi-factor authentication in the | ||
// client-side when the server supports it. | ||
// Modifications copyright (c) 2021, Oracle and/or its affiliates. | ||
'use strict'; | ||
@@ -5,2 +11,3 @@ | ||
const Packets = require('../packets/index.js'); | ||
const ClientConstants = require('../constants/client'); | ||
const ClientHandshake = require('./client_handshake.js'); | ||
@@ -15,2 +22,6 @@ const CharsetToEncoding = require('../constants/charset_encodings.js'); | ||
this.password = options.password; | ||
// "password1" is an alias of "password" | ||
this.password1 = options.password; | ||
this.password2 = options.password2; | ||
this.password3 = options.password3; | ||
this.database = options.database; | ||
@@ -20,2 +31,3 @@ this.passwordSha1 = options.passwordSha1; | ||
this.currentConfig = options.currentConfig; | ||
this.authenticationFactor = 0; | ||
} | ||
@@ -41,2 +53,9 @@ start(packet, connection) { | ||
connection.writePacket(newPacket.toPacket()); | ||
// check if the server supports multi-factor authentication | ||
const multiFactorAuthentication = connection.serverCapabilityFlags & ClientConstants.MULTI_FACTOR_AUTHENTICATION; | ||
if (multiFactorAuthentication) { | ||
// if the server supports multi-factor authentication, we enable it in | ||
// the client | ||
this.authenticationFactor = 1; | ||
} | ||
return ChangeUser.prototype.handshakeResult; | ||
@@ -43,0 +62,0 @@ } |
@@ -6,2 +6,7 @@ // This file was modified by Oracle on June 17, 2021. | ||
// This file was modified by Oracle on September 21, 2021. | ||
// Handshake workflow now supports additional authentication factors requested | ||
// by the server. | ||
// Modifications copyright (c) 2021, Oracle and/or its affiliates. | ||
'use strict'; | ||
@@ -30,2 +35,3 @@ | ||
this.clientFlags = clientFlags; | ||
this.authenticationFactor = 0; | ||
} | ||
@@ -56,2 +62,10 @@ | ||
this.password = connection.config.password; | ||
// "password1" is an alias to the original "password" value | ||
// to make it easier to integrate multi-factor authentication | ||
this.password1 = connection.config.password; | ||
// "password2" and "password3" are the 2nd and 3rd factor authentication | ||
// passwords, which can be undefined depending on the authentication | ||
// plugin being used | ||
this.password2 = connection.config.password2; | ||
this.password3 = connection.config.password3; | ||
this.passwordSha1 = connection.config.passwordSha1; | ||
@@ -115,2 +129,8 @@ this.database = connection.config.database; | ||
this.handshake.capabilityFlags & ClientConstants.SSL; | ||
// multi factor authentication is enabled with the | ||
// "MULTI_FACTOR_AUTHENTICATION" capability and should only be used if it | ||
// is supported by the server | ||
const multiFactorAuthentication = | ||
this.handshake.capabilityFlags & ClientConstants.MULTI_FACTOR_AUTHENTICATION; | ||
this.clientFlags = this.clientFlags | multiFactorAuthentication; | ||
// use compression only if requested by client and supported by server | ||
@@ -148,2 +168,7 @@ connection.config.compress = | ||
} | ||
if (multiFactorAuthentication) { | ||
// if the server supports multi-factor authentication, we enable it in | ||
// the client | ||
this.authenticationFactor = 1; | ||
} | ||
return ClientHandshake.prototype.handshakeResult; | ||
@@ -154,3 +179,5 @@ } | ||
const marker = packet.peekByte(); | ||
if (marker === 0xfe || marker === 1) { | ||
// packet can be OK_Packet, ERR_Packet, AuthSwitchRequest, AuthNextFactor | ||
// or AuthMoreData | ||
if (marker === 0xfe || marker === 1 || marker === 0x02) { | ||
const authSwitch = require('./auth_switch'); | ||
@@ -161,2 +188,14 @@ try { | ||
} else { | ||
// if authenticationFactor === 0, it means the server does not support | ||
// the multi-factor authentication capability | ||
if (this.authenticationFactor !== 0) { | ||
// if we are past the first authentication factor, we should use the | ||
// corresponding password (if there is one) | ||
connection.config.password = this[`password${this.authenticationFactor}`]; | ||
// update the current authentication factor | ||
this.authenticationFactor += 1; | ||
} | ||
// if marker === 0x02, it means it is an AuthNextFactor packet, | ||
// which is similar in structure to an AuthSwitchRequest packet, | ||
// so, we can use it directly | ||
authSwitch.authSwitchRequest(packet, connection, this); | ||
@@ -163,0 +202,0 @@ } |
@@ -58,3 +58,4 @@ 'use strict'; | ||
this.query, | ||
connection.config.charsetNumber | ||
connection.config.charsetNumber, | ||
this.options.values | ||
); | ||
@@ -61,0 +62,0 @@ connection.writePacket(cmdPacket.toPacket(1)); |
@@ -10,3 +10,3 @@ 'use strict'; | ||
super(); | ||
this.done = callback; | ||
this.onResult = callback; | ||
} | ||
@@ -22,4 +22,4 @@ | ||
); | ||
if (this.done) { | ||
this.done(); | ||
if (this.onResult) { | ||
this.onResult(); | ||
} | ||
@@ -26,0 +26,0 @@ connection.writePacket(quit); |
@@ -72,2 +72,7 @@ 'use strict'; | ||
_isStatement(query, name) { | ||
const firstWord = query.split(' ')[0].toUpperCase(); | ||
return firstWord === name; | ||
} | ||
dispatchCommands(packet, connection) { | ||
@@ -79,2 +84,26 @@ // command from client to server | ||
switch (commandCode) { | ||
case CommandCode.STMT_PREPARE: | ||
if (connection.listeners('stmt_prepare').length) { | ||
const query = packet.readString(undefined, encoding); | ||
connection.emit('stmt_prepare', query); | ||
} else { | ||
connection.writeError({ | ||
code: Errors.HA_ERR_INTERNAL_ERROR, | ||
message: | ||
'No query handler for prepared statements.' | ||
}); | ||
} | ||
break; | ||
case CommandCode.STMT_EXECUTE: | ||
if (connection.listeners('stmt_execute').length) { | ||
const { stmtId, flags, iterationCount, values } = Packets.Execute.fromPacket(packet, encoding); | ||
connection.emit('stmt_execute', stmtId, flags, iterationCount, values); | ||
} else { | ||
connection.writeError({ | ||
code: Errors.HA_ERR_INTERNAL_ERROR, | ||
message: | ||
'No query handler for execute statements.' | ||
}); | ||
} | ||
break; | ||
case CommandCode.QUIT: | ||
@@ -98,3 +127,9 @@ if (connection.listeners('quit').length) { | ||
const query = packet.readString(undefined, encoding); | ||
connection.emit('query', query); | ||
if (this._isStatement(query, 'PREPARE') || this._isStatement(query, 'SET')) { | ||
connection.emit('stmt_prepare', query); | ||
} | ||
else if (this._isStatement(query, 'EXECUTE')) { | ||
connection.emit('stmt_execute', null, null, null, null, query); | ||
} | ||
else connection.emit('query', query); | ||
} else { | ||
@@ -101,0 +136,0 @@ connection.writeError({ |
@@ -0,1 +1,8 @@ | ||
// This file was modified by Oracle on September 21, 2021. | ||
// New connection options for additional authentication factors were | ||
// introduced. | ||
// Multi-factor authentication capability is now enabled if one of these | ||
// options is used. | ||
// Modifications copyright (c) 2021, Oracle and/or its affiliates. | ||
'use strict'; | ||
@@ -33,2 +40,7 @@ | ||
password: 1, | ||
// with multi-factor authentication, the main password (used for the first | ||
// authentication factor) can be provided via password1 | ||
password1: 1, | ||
password2: 1, | ||
password3: 1, | ||
passwordSha1: 1, | ||
@@ -85,3 +97,8 @@ pool: 1, | ||
this.user = options.user || undefined; | ||
this.password = options.password || undefined; | ||
// for the purpose of multi-factor authentication, or not, the main | ||
// password (used for the 1st authentication factor) can also be | ||
// provided via the "password1" option | ||
this.password = options.password || options.password1 || undefined; | ||
this.password2 = options.password2 || undefined; | ||
this.password3 = options.password3 || undefined; | ||
this.passwordSha1 = options.passwordSha1 || undefined; | ||
@@ -133,3 +150,3 @@ this.database = options.database; | ||
// connection string.. | ||
this.timezone = `+${this.timezone.substr(1)}`; | ||
this.timezone = `+${this.timezone.slice(1)}`; | ||
} | ||
@@ -242,3 +259,3 @@ if (this.ssl) { | ||
port: parsedUrl.port, | ||
database: parsedUrl.pathname.substr(1), | ||
database: parsedUrl.pathname.slice(1), | ||
user: parsedUrl.username, | ||
@@ -245,0 +262,0 @@ password: parsedUrl.password |
@@ -11,2 +11,7 @@ // This file was modified by Oracle on June 1, 2021. | ||
// This file was modified by Oracle on September 21, 2021. | ||
// The changes involve passing additional authentication factor passwords | ||
// to the ChangeUser Command instance. | ||
// Modifications copyright (c) 2021, Oracle and/or its affiliates. | ||
'use strict'; | ||
@@ -116,3 +121,3 @@ | ||
// some fatal error or the server sent an error packet instead of | ||
// an hello packet (for example, 'Too many connactions' error) | ||
// an hello packet (for example, 'Too many connections' error) | ||
if (!handshakeCommand.handshake || this._fatalError || this._protocolError) { | ||
@@ -131,5 +136,5 @@ return; | ||
} | ||
// in case there was no initiall handshake but we need to read sting, assume it utf-8 | ||
// in case there was no initial handshake but we need to read sting, assume it utf-8 | ||
// most common example: "Too many connections" error ( packet is sent immediately on connection attempt, we don't know server encoding yet) | ||
// will be overwrittedn with actial encoding value as soon as server handshake packet is received | ||
// will be overwritten with actual encoding value as soon as server handshake packet is received | ||
this.serverEncoding = 'utf8'; | ||
@@ -180,3 +185,3 @@ if (this.config.connectTimeout) { | ||
// Do not throw an error when a connection ends with a RST,ACK packet | ||
if (err.errno === 'ECONNRESET' && this._closing) { | ||
if (err.code === 'ECONNRESET' && this._closing) { | ||
return; | ||
@@ -563,3 +568,3 @@ } | ||
this.handlePacket(packet); | ||
// don't resume if packet hander paused connection | ||
// don't resume if packet handler paused connection | ||
if (this._paused) { | ||
@@ -679,3 +684,8 @@ return; | ||
user: options.user || this.config.user, | ||
password: options.password || this.config.password, | ||
// for the purpose of multi-factor authentication, or not, the main | ||
// password (used for the 1st authentication factor) can also be | ||
// provided via the "password1" option | ||
password: options.password || options.password1 || this.config.password || this.config.password1, | ||
password2: options.password2 || this.config.password2, | ||
password3: options.password3 || this.config.password3, | ||
passwordSha1: options.passwordSha1 || this.config.passwordSha1, | ||
@@ -682,0 +692,0 @@ database: options.database || this.config.database, |
@@ -107,3 +107,2 @@ 'use strict'; | ||
'cp1250', | ||
'utf8', | ||
'utf16', | ||
@@ -133,2 +132,3 @@ 'utf16', | ||
'utf16', | ||
'utf16', | ||
'utf8', | ||
@@ -314,3 +314,6 @@ 'utf8', | ||
'utf8', | ||
'utf8', | ||
'utf8', | ||
'utf8', | ||
'utf8' | ||
]; |
@@ -226,24 +226,52 @@ 'use strict'; | ||
exports.GB18030_UNICODE_520_CI = 250; | ||
exports.UTF8_GENERAL50_CI = 253; | ||
exports.UTF8_GENERAL50_CI = 253; // deprecated | ||
exports.UTF8MB4_0900_AI_CI = 255; | ||
exports.UTF8MB4_CS_0900_AI_CI = 266; | ||
exports.UTF8MB4_DA_0900_AI_CI = 267; | ||
exports.UTF8MB4_DE_PB_0900_AI_CI = 256; | ||
exports.UTF8MB4_EO_0900_AI_CI = 273; | ||
exports.UTF8MB4_ES_0900_AI_CI = 263; | ||
exports.UTF8MB4_ES_TRAD_0900_AI_CI = 270; | ||
exports.UTF8MB4_ET_0900_AI_CI = 262; | ||
exports.UTF8MB4_HR_0900_AI_CI = 275; | ||
exports.UTF8MB4_HU_0900_AI_CI = 274; | ||
exports.UTF8MB4_IS_0900_AI_CI = 257; | ||
exports.UTF8MB4_LA_0900_AI_CI = 271; | ||
exports.UTF8MB4_LT_0900_AI_CI = 268; | ||
exports.UTF8MB4_LV_0900_AI_CI = 258; | ||
exports.UTF8MB4_PL_0900_AI_CI = 261; | ||
exports.UTF8MB4_RO_0900_AI_CI = 259; | ||
exports.UTF8MB4_SK_0900_AI_CI = 269; | ||
exports.UTF8MB4_SL_0900_AI_CI = 260; | ||
exports.UTF8MB4_PL_0900_AI_CI = 261; | ||
exports.UTF8MB4_ET_0900_AI_CI = 262; | ||
exports.UTF8MB4_ES_0900_AI_CI = 263; | ||
exports.UTF8MB4_SV_0900_AI_CI = 264; | ||
exports.UTF8MB4_TR_0900_AI_CI = 265; | ||
exports.UTF8MB4_CS_0900_AI_CI = 266; | ||
exports.UTF8MB4_DA_0900_AI_CI = 267; | ||
exports.UTF8MB4_LT_0900_AI_CI = 268; | ||
exports.UTF8MB4_SK_0900_AI_CI = 269; | ||
exports.UTF8MB4_ES_TRAD_0900_AI_CI = 270; | ||
exports.UTF8MB4_LA_0900_AI_CI = 271; | ||
exports.UTF8MB4_EO_0900_AI_CI = 273; | ||
exports.UTF8MB4_HU_0900_AI_CI = 274; | ||
exports.UTF8MB4_HR_0900_AI_CI = 275; | ||
exports.UTF8MB4_VI_0900_AI_CI = 277; | ||
exports.UTF8MB4_0900_AS_CS = 278; | ||
exports.UTF8MB4_DE_PB_0900_AS_CS = 279; | ||
exports.UTF8MB4_IS_0900_AS_CS = 280; | ||
exports.UTF8MB4_LV_0900_AS_CS = 281; | ||
exports.UTF8MB4_RO_0900_AS_CS = 282; | ||
exports.UTF8MB4_SL_0900_AS_CS = 283; | ||
exports.UTF8MB4_PL_0900_AS_CS = 284; | ||
exports.UTF8MB4_ET_0900_AS_CS = 285; | ||
exports.UTF8MB4_ES_0900_AS_CS = 286; | ||
exports.UTF8MB4_SV_0900_AS_CS = 287; | ||
exports.UTF8MB4_TR_0900_AS_CS = 288; | ||
exports.UTF8MB4_CS_0900_AS_CS = 289; | ||
exports.UTF8MB4_DA_0900_AS_CS = 290; | ||
exports.UTF8MB4_LT_0900_AS_CS = 291; | ||
exports.UTF8MB4_SK_0900_AS_CS = 292; | ||
exports.UTF8MB4_ES_TRAD_0900_AS_CS = 293; | ||
exports.UTF8MB4_LA_0900_AS_CS = 294; | ||
exports.UTF8MB4_EO_0900_AS_CS = 296; | ||
exports.UTF8MB4_HU_0900_AS_CS = 297; | ||
exports.UTF8MB4_HR_0900_AS_CS = 298; | ||
exports.UTF8MB4_VI_0900_AS_CS = 300; | ||
exports.UTF8MB4_JA_0900_AS_CS = 303; | ||
exports.UTF8MB4_JA_0900_AS_CS_KS = 304; | ||
exports.UTF8MB4_0900_AS_CI = 305; | ||
exports.UTF8MB4_RU_0900_AI_CI = 306; | ||
exports.UTF8MB4_RU_0900_AS_CS = 307; | ||
exports.UTF8MB4_ZH_0900_AS_CS = 308; | ||
exports.UTF8MB4_0900_BIN = 309; | ||
@@ -250,0 +278,0 @@ // short aliases |
@@ -0,1 +1,7 @@ | ||
// This file was modified by Oracle on September 21, 2021. | ||
// New capability for multi-factor authentication based on mandatory session | ||
// trackers, that are signaled with an extra single-byte prefix on new | ||
// versions of the MySQL server. | ||
// Modifications copyright (c) 2021, Oracle and/or its affiliates. | ||
'use strict'; | ||
@@ -32,1 +38,3 @@ | ||
exports.REMEMBER_OPTIONS = 0x80000000; | ||
exports.MULTI_FACTOR_AUTHENTICATION = 0x10000000; /* multi-factor authentication */ |
'use strict'; | ||
module.exports = { | ||
0x00: 'DECIMAL', // aka DECIMAL | ||
0x01: 'TINY', // aka TINYINT, 1 byte | ||
0x02: 'SHORT', // aka SMALLINT, 2 bytes | ||
0x03: 'LONG', // aka INT, 4 bytes | ||
0x04: 'FLOAT', // aka FLOAT, 4-8 bytes | ||
0x05: 'DOUBLE', // aka DOUBLE, 8 bytes | ||
0x06: 'NULL', // NULL (used for prepared statements, I think) | ||
0x07: 'TIMESTAMP', // aka TIMESTAMP | ||
0x08: 'LONGLONG', // aka BIGINT, 8 bytes | ||
0x09: 'INT24', // aka MEDIUMINT, 3 bytes | ||
0x0a: 'DATE', // aka DATE | ||
0x0b: 'TIME', // aka TIME | ||
0x0c: 'DATETIME', // aka DATETIME | ||
0x0d: 'YEAR', // aka YEAR, 1 byte (don't ask) | ||
0x0e: 'NEWDATE', // aka ? | ||
0x0f: 'VARCHAR', // aka VARCHAR (?) | ||
0x10: 'BIT', // aka BIT, 1-8 byte | ||
0xf5: 'JSON', | ||
0xf6: 'NEWDECIMAL', // aka DECIMAL | ||
0xf7: 'ENUM', // aka ENUM | ||
0xf8: 'SET', // aka SET | ||
0xf9: 'TINY_BLOB', // aka TINYBLOB, TINYTEXT | ||
0xfa: 'MEDIUM_BLOB', // aka MEDIUMBLOB, MEDIUMTEXT | ||
0xfb: 'LONG_BLOB', // aka LONGBLOG, LONGTEXT | ||
0xfc: 'BLOB', // aka BLOB, TEXT | ||
0xfd: 'VAR_STRING', // aka VARCHAR, VARBINARY | ||
0xfe: 'STRING', // aka CHAR, BINARY | ||
0xff: 'GEOMETRY' // aka GEOMETRY | ||
}; | ||
// Manually extracted from mysql-5.5.23/include/mysql_com.h | ||
// some more info here: http://dev.mysql.com/doc/refman/5.5/en/c-api-prepared-statement-type-codes.html | ||
exports.DECIMAL = 0x00; // aka DECIMAL (http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html) | ||
exports.TINY = 0x01; // aka TINYINT, 1 byte | ||
exports.SHORT = 0x02; // aka SMALLINT, 2 bytes | ||
exports.LONG = 0x03; // aka INT, 4 bytes | ||
exports.FLOAT = 0x04; // aka FLOAT, 4-8 bytes | ||
exports.DOUBLE = 0x05; // aka DOUBLE, 8 bytes | ||
exports.NULL = 0x06; // NULL (used for prepared statements, I think) | ||
exports.TIMESTAMP = 0x07; // aka TIMESTAMP | ||
exports.LONGLONG = 0x08; // aka BIGINT, 8 bytes | ||
exports.INT24 = 0x09; // aka MEDIUMINT, 3 bytes | ||
exports.DATE = 0x0a; // aka DATE | ||
exports.TIME = 0x0b; // aka TIME | ||
exports.DATETIME = 0x0c; // aka DATETIME | ||
exports.YEAR = 0x0d; // aka YEAR, 1 byte (don't ask) | ||
exports.NEWDATE = 0x0e; // aka ? | ||
exports.VARCHAR = 0x0f; // aka VARCHAR (?) | ||
exports.BIT = 0x10; // aka BIT, 1-8 byte | ||
exports.JSON = 0xf5; | ||
exports.NEWDECIMAL = 0xf6; // aka DECIMAL | ||
exports.ENUM = 0xf7; // aka ENUM | ||
exports.SET = 0xf8; // aka SET | ||
exports.TINY_BLOB = 0xf9; // aka TINYBLOB, TINYTEXT | ||
exports.MEDIUM_BLOB = 0xfa; // aka MEDIUMBLOB, MEDIUMTEXT | ||
exports.LONG_BLOB = 0xfb; // aka LONGBLOG, LONGTEXT | ||
exports.BLOB = 0xfc; // aka BLOB, TEXT | ||
exports.VAR_STRING = 0xfd; // aka VARCHAR, VARBINARY | ||
exports.STRING = 0xfe; // aka CHAR, BINARY | ||
exports.GEOMETRY = 0xff; // aka GEOMETRY | ||
module.exports.DECIMAL = 0x00; // aka DECIMAL (http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html) | ||
module.exports.TINY = 0x01; // aka TINYINT, 1 byte | ||
module.exports.SHORT = 0x02; // aka SMALLINT, 2 bytes | ||
module.exports.LONG = 0x03; // aka INT, 4 bytes | ||
module.exports.FLOAT = 0x04; // aka FLOAT, 4-8 bytes | ||
module.exports.DOUBLE = 0x05; // aka DOUBLE, 8 bytes | ||
module.exports.NULL = 0x06; // NULL (used for prepared statements, I think) | ||
module.exports.TIMESTAMP = 0x07; // aka TIMESTAMP | ||
module.exports.LONGLONG = 0x08; // aka BIGINT, 8 bytes | ||
module.exports.INT24 = 0x09; // aka MEDIUMINT, 3 bytes | ||
module.exports.DATE = 0x0a; // aka DATE | ||
module.exports.TIME = 0x0b; // aka TIME | ||
module.exports.DATETIME = 0x0c; // aka DATETIME | ||
module.exports.YEAR = 0x0d; // aka YEAR, 1 byte (don't ask) | ||
module.exports.NEWDATE = 0x0e; // aka ? | ||
module.exports.VARCHAR = 0x0f; // aka VARCHAR (?) | ||
module.exports.BIT = 0x10; // aka BIT, 1-8 byte | ||
module.exports.JSON = 0xf5; | ||
module.exports.NEWDECIMAL = 0xf6; // aka DECIMAL | ||
module.exports.ENUM = 0xf7; // aka ENUM | ||
module.exports.SET = 0xf8; // aka SET | ||
module.exports.TINY_BLOB = 0xf9; // aka TINYBLOB, TINYTEXT | ||
module.exports.MEDIUM_BLOB = 0xfa; // aka MEDIUMBLOB, MEDIUMTEXT | ||
module.exports.LONG_BLOB = 0xfb; // aka LONGBLOG, LONGTEXT | ||
module.exports.BLOB = 0xfc; // aka BLOB, TEXT | ||
module.exports.VAR_STRING = 0xfd; // aka VARCHAR, VARBINARY | ||
module.exports.STRING = 0xfe; // aka CHAR, BINARY | ||
module.exports.GEOMETRY = 0xff; // aka GEOMETRY |
@@ -28,3 +28,5 @@ 'use strict'; | ||
try { | ||
highlightFn = require('cardinal').highlight; | ||
// the purpose of this is to prevent projects using Webpack from displaying a warning during runtime if cardinal is not a dependency | ||
const REQUIRE_TERMINATOR = ''; | ||
highlightFn = require(`cardinal${REQUIRE_TERMINATOR}`).highlight; | ||
} catch (err) { | ||
@@ -31,0 +33,0 @@ highlightFn = text => { |
@@ -55,2 +55,3 @@ 'use strict'; | ||
this.columnType = packet.readInt8(); | ||
this.type = this.columnType; | ||
this.flags = packet.readInt16(); | ||
@@ -71,2 +72,3 @@ this.decimals = packet.readInt8(); | ||
columnType: this.columnType, | ||
type: this.columnType, | ||
flags: this.flags, | ||
@@ -73,0 +75,0 @@ decimals: this.decimals |
@@ -84,2 +84,64 @@ 'use strict'; | ||
static fromPacket(packet, encoding) { | ||
const stmtId = packet.readInt32(); | ||
const flags = packet.readInt8(); | ||
const iterationCount = packet.readInt32(); | ||
let i = packet.offset; | ||
while (i < packet.end - 1) { | ||
if((packet.buffer[i+1] === Types.VAR_STRING | ||
|| packet.buffer[i+1] === Types.NULL | ||
|| packet.buffer[i+1] === Types.DOUBLE | ||
|| packet.buffer[i+1] === Types.TINY | ||
|| packet.buffer[i+1] === Types.DATETIME | ||
|| packet.buffer[i+1] === Types.JSON) && packet.buffer[i] === 1 && packet.buffer[i+2] === 0) { | ||
break; | ||
} | ||
else { | ||
packet.readInt8() | ||
} | ||
i++; | ||
} | ||
const types = []; | ||
for(let i = packet.offset + 1; i < packet.end - 1; i++) { | ||
if((packet.buffer[i] === Types.VAR_STRING | ||
|| packet.buffer[i] === Types.NULL | ||
|| packet.buffer[i] === Types.DOUBLE | ||
|| packet.buffer[i] === Types.TINY | ||
|| packet.buffer[i] === Types.DATETIME | ||
|| packet.buffer[i] === Types.JSON) && packet.buffer[i + 1] === 0) { | ||
types.push(packet.buffer[i]); | ||
packet.skip(2); | ||
} | ||
} | ||
packet.skip(1); | ||
const values = []; | ||
for(let i = 0; i < types.length; i++) { | ||
if(types[i] === Types.VAR_STRING) { | ||
values.push(packet.readLengthCodedString(encoding)) | ||
} | ||
else if(types[i] === Types.DOUBLE) { | ||
values.push(packet.readDouble()) | ||
} | ||
else if(types[i] === Types.TINY) { | ||
values.push(packet.readInt8()) | ||
} | ||
else if(types[i] === Types.DATETIME) { | ||
values.push(packet.readDateTime()) | ||
} | ||
else if(types[i] === Types.JSON) { | ||
values.push(JSON.parse(packet.readLengthCodedString(encoding))) | ||
} | ||
if(types[i] === Types.NULL) { | ||
values.push(null) | ||
} | ||
} | ||
return { stmtId, flags, iterationCount, values }; | ||
} | ||
toPacket() { | ||
@@ -86,0 +148,0 @@ // TODO: don't try to calculate packet length in advance, allocate some big buffer in advance (header + 256 bytes?) |
@@ -6,2 +6,6 @@ // This file was modified by Oracle on June 1, 2021. | ||
// This file was modified by Oracle on September 21, 2021. | ||
// The new AuthNextFactor packet is now available. | ||
// Modifications copyright (c) 2021, Oracle and/or its affiliates. | ||
'use strict'; | ||
@@ -11,2 +15,3 @@ | ||
const AuthNextFactor = require('./auth_next_factor'); | ||
const AuthSwitchRequest = require('./auth_switch_request'); | ||
@@ -32,2 +37,3 @@ const AuthSwitchRequestMoreData = require('./auth_switch_request_more_data'); | ||
const ctorMap = { | ||
AuthNextFactor, | ||
AuthSwitchRequest, | ||
@@ -34,0 +40,0 @@ AuthSwitchRequestMoreData, |
@@ -177,3 +177,3 @@ 'use strict'; | ||
conn.release(); | ||
throw e; | ||
return cb(e); | ||
} | ||
@@ -180,0 +180,0 @@ }); |
{ | ||
"name": "mysql2", | ||
"version": "2.3.3", | ||
"version": "3.0.0-rc.1", | ||
"description": "fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS", | ||
@@ -9,2 +9,3 @@ "main": "index.js", | ||
}, | ||
"typings": "typings/mysql/index", | ||
"scripts": { | ||
@@ -21,3 +22,4 @@ "lint": "npm run lint:docs && npm run lint:code", | ||
"eslint-check": "eslint --print-config .eslintrc | eslint-config-prettier-check", | ||
"wait-port": "wait-on" | ||
"wait-port": "wait-on", | ||
"type-test": "node ./node_modules/typescript/bin/tsc -p tests.json && mocha typings/test --timeout 10000" | ||
}, | ||
@@ -58,2 +60,4 @@ "lint-staged": { | ||
"dependencies": { | ||
"@types/chai": "^4.3.3", | ||
"chai": "^4.3.6", | ||
"denque": "^2.0.1", | ||
@@ -64,2 +68,3 @@ "generate-function": "^2.3.1", | ||
"lru-cache": "^6.0.0", | ||
"mocha": "^10.0.0", | ||
"named-placeholders": "^1.1.2", | ||
@@ -70,2 +75,4 @@ "seq-queue": "^0.0.5", | ||
"devDependencies": { | ||
"@types/mocha": "^9.1.1", | ||
"@types/node": "^18.7.1", | ||
"@typescript-eslint/eslint-plugin": "^4.33.0", | ||
@@ -72,0 +79,0 @@ "@typescript-eslint/parser": "^4.33.0", |
@@ -8,3 +8,4 @@ import { | ||
ConnectionOptions, | ||
PoolOptions | ||
PoolOptions, | ||
Pool as CorePool | ||
} from './index'; | ||
@@ -66,3 +67,4 @@ | ||
unprepare(sql: string): void; | ||
prepare(options: string | QueryOptions): Promise<PreparedStatementInfo>; | ||
unprepare(sql: string | QueryOptions): void; | ||
@@ -86,2 +88,3 @@ end(options?: any): Promise<void>; | ||
export interface PoolConnection extends Connection { | ||
connection: Connection; | ||
release(): void; | ||
@@ -135,2 +138,9 @@ } | ||
end(): Promise<void>; | ||
escape(value: any): string; | ||
escapeId(value: string): string; | ||
escapeId(values: string[]): string; | ||
format(sql: string, values?: any | any[] | { [param: string]: any }): string; | ||
pool: CorePool; | ||
} | ||
@@ -143,1 +153,10 @@ | ||
export function createPool(config: PoolOptions): Pool; | ||
export interface PreparedStatementInfo { | ||
close(): Promise<void>; | ||
execute(parameters: any[]): Promise<[RowDataPacket[][] | RowDataPacket[] | OkPacket | OkPacket[] | ResultSetHeader, FieldPacket[]]>; | ||
} | ||
export interface PromisePoolConnection extends Connection { | ||
destroy(): any; | ||
} |
@@ -164,4 +164,14 @@ 'use strict'; | ||
return new this.Promise((resolve, reject) => { | ||
const done = makeDoneCb(resolve, reject, localErr); | ||
c.ping(done); | ||
c.ping(err => { | ||
if (err) { | ||
localErr.message = err.message; | ||
localErr.code = err.code; | ||
localErr.errno = err.errno; | ||
localErr.sqlState = err.sqlState; | ||
localErr.sqlMessage = err.sqlMessage; | ||
reject(localErr); | ||
} else { | ||
resolve(true); | ||
} | ||
}); | ||
}); | ||
@@ -168,0 +178,0 @@ } |
@@ -9,4 +9,6 @@ ## Node MySQL 2 | ||
[![Windows Build][appveyor-image]][appveyor-url] | ||
[![License][license-image]][license-url] | ||
[![License][license-image]][license-url] | ||
[简体中文 Simplified Chinese](./documentation_zh-cn/) | ||
> MySQL client for Node.js with focus on performance. Supports prepared statements, non-utf8 encodings, binary log protocol, compression, ssl [much more](https://github.com/sidorares/node-mysql2/tree/master/documentation) | ||
@@ -250,4 +252,6 @@ | ||
If you find any incompatibility with [Node MySQL][node-mysql], Please report via Issue tracker. We will fix reported incompatibility on priority basis. | ||
One known incompatibility is that `DECIMAL` values are returned as strings whereas in [Node MySQL][node-mysql] they are returned as numbers. This includes the result of `SUM()` and `AVG()` functions when applied to `INTEGER` arguments. This is done deliberately to avoid loss of precision - see https://github.com/sidorares/node-mysql2/issues/935. | ||
If you find any other incompatibility with [Node MySQL][node-mysql], Please report via Issue tracker. We will fix reported incompatibility on priority basis. | ||
## Documentation | ||
@@ -254,0 +258,0 @@ |
@@ -10,12 +10,20 @@ | ||
import BaseQuery = require('./lib/protocol/sequences/Query'); | ||
import BasePrepare = require('./lib/protocol/sequences/Prepare'); | ||
import {QueryOptions, StreamOptions, QueryError} from './lib/protocol/sequences/Query'; | ||
import {PrepareStatementInfo} from './lib/protocol/sequences/Prepare'; | ||
import Server = require('./lib/Server'); | ||
export function createConnection(connectionUri: string): Connection; | ||
export function createConnection(config: BaseConnection.ConnectionOptions): Connection; | ||
export function createPool(config: BasePool.PoolOptions): Pool; | ||
export function createPool(config: BasePool.PoolOptions): BasePool; | ||
export function createPoolCluster(config?: BasePoolCluster.PoolClusterOptions): PoolCluster; | ||
export function escape(value: any): string; | ||
export function escapeId(value: any): string; | ||
export function format(sql: string): string; | ||
export function format(sql: string, values: any[]): string; | ||
export function format(sql: string, values: any): string; | ||
export function format(sql: string, values: any[], stringifyObjects?: boolean, timeZone?: string): string; | ||
export function format(sql: string, values: any, stringifyObjects?: boolean, timeZone?: string): string; | ||
export function raw(sql: string): { | ||
toSqlString: () => string | ||
}; | ||
export function createServer(handler: (conn: BaseConnection) => any): Server; | ||
@@ -28,3 +36,4 @@ export { | ||
QueryOptions, | ||
QueryError | ||
QueryError, | ||
PrepareStatementInfo | ||
}; | ||
@@ -39,1 +48,2 @@ export * from './lib/protocol/packets/index'; | ||
export interface Query extends BaseQuery {} | ||
export interface Prepare extends BasePrepare {} |
@@ -0,3 +1,8 @@ | ||
// This file was modified by Oracle on November 04, 2021. | ||
// Type definitions and corresponding descriptions were introduced for the | ||
// connection options relevant for multifactor authentication. | ||
// Modifications copyright (c) 2021, Oracle and/or its affiliates. | ||
import Query = require('./protocol/sequences/Query'); | ||
import Prepare = require('./protocol/sequences/Prepare'); | ||
import {OkPacket, FieldPacket, RowDataPacket, ResultSetHeader} from './protocol/packets/index'; | ||
@@ -20,2 +25,22 @@ import {EventEmitter} from 'events'; | ||
/** | ||
* Alias for the MySQL user password. Makes a bit more sense in a multifactor authentication setup (see | ||
* "password2" and "password3") | ||
*/ | ||
password1?: string; | ||
/** | ||
* 2nd factor authentication password. Mandatory when the authentication policy for the MySQL user account | ||
* requires an additional authentication method that needs a password. | ||
* https://dev.mysql.com/doc/refman/8.0/en/multifactor-authentication.html | ||
*/ | ||
password2?: string; | ||
/** | ||
* 3rd factor authentication password. Mandatory when the authentication policy for the MySQL user account | ||
* requires two additional authentication methods and the last one needs a password. | ||
* https://dev.mysql.com/doc/refman/8.0/en/multifactor-authentication.html | ||
*/ | ||
password3?: string; | ||
/** | ||
* Name of the database to use for this connection | ||
@@ -168,5 +193,5 @@ */ | ||
/** | ||
* A string holding the PEM encoded private key | ||
* Either a string/buffer or list of strings/Buffers holding the PEM encoded private key(s) to use | ||
*/ | ||
key?: string; | ||
key?: string | string[] | Buffer | Buffer[]; | ||
@@ -179,10 +204,10 @@ /** | ||
/** | ||
* A string holding the PEM encoded certificate | ||
* A string/buffer or list of strings/Buffers holding the PEM encoded certificate(s) | ||
*/ | ||
cert?: string; | ||
cert?: string | string[] | Buffer | Buffer[]; | ||
/** | ||
* Either a string or list of strings of PEM encoded CA certificates to trust. | ||
* Either a string/Buffer or list of strings/Buffers of PEM encoded CA certificates to trust. | ||
*/ | ||
ca?: string | string[]; | ||
ca?: string | string[] | Buffer | Buffer[]; | ||
@@ -203,2 +228,7 @@ /** | ||
rejectUnauthorized?: boolean; | ||
/** | ||
* Configure the minimum supported version of SSL, the default is TLSv1.2. | ||
*/ | ||
minVersion?: string; | ||
} | ||
@@ -247,5 +277,11 @@ } | ||
rollback(callback: () => void): void; | ||
rollback(callback: (err: Query.QueryError | null) => void): void; | ||
execute(sql: string, values: Array<any>, cb: (err: any, rows: Array<any>, fields: Array<any>) => any): any; | ||
unprepare(sql: string): any; | ||
serverHandshake(args: any): any; | ||
} | ||
export = Connection; |
@@ -39,3 +39,3 @@ | ||
*/ | ||
enableKeepAlive?: true; | ||
enableKeepAlive?: boolean; | ||
@@ -53,3 +53,3 @@ /** | ||
getConnection(callback: (err: NodeJS.ErrnoException, connection: PoolConnection) => any): void; | ||
getConnection(callback: (err: NodeJS.ErrnoException | null, connection: PoolConnection) => any): void; | ||
@@ -65,4 +65,6 @@ query<T extends RowDataPacket[][] | RowDataPacket[] | OkPacket | OkPacket[] | ResultSetHeader>(sql: string, callback?: (err: Query.QueryError | null, result: T, fields: FieldPacket[]) => any): Query; | ||
on(event: 'connection', listener: (connection: PoolConnection) => any): this; | ||
promise(promiseImpl?: any): any; | ||
} | ||
export = Pool; |
import Connection = require('./Connection'); | ||
import PoolConnection = require('./PoolConnection'); | ||
import {EventEmitter} from 'events'; | ||
import {PoolOptions} from './Pool'; | ||
@@ -40,4 +40,4 @@ declare namespace PoolCluster { | ||
add(config: PoolCluster.PoolClusterOptions): void; | ||
add(group: string, config: PoolCluster.PoolClusterOptions): void; | ||
add(config: PoolOptions): void; | ||
add(group: string, config: PoolOptions): void; | ||
@@ -44,0 +44,0 @@ end(): void; |
@@ -5,2 +5,3 @@ | ||
declare class PoolConnection extends Connection { | ||
connection: Connection; | ||
release(): void; | ||
@@ -7,0 +8,0 @@ } |
@@ -7,2 +7,4 @@ | ||
import ResultSetHeader = require('./ResultSetHeader'); | ||
import OkPacketParams = require('./params/OkPacketParams'); | ||
import ErrorPacketParams = require('./params/ErrorPacketParams'); | ||
@@ -14,3 +16,5 @@ export { | ||
Field, | ||
ResultSetHeader | ||
ResultSetHeader, | ||
OkPacketParams, | ||
ErrorPacketParams | ||
}; |
@@ -20,2 +20,7 @@ | ||
/** | ||
* This overrides the namedPlaceholders option set at the connection level. | ||
*/ | ||
namedPlaceholders?: boolean; | ||
/** | ||
* Every operation takes an optional inactivity timeout option. This allows you to specify appropriate timeouts for | ||
@@ -58,5 +63,10 @@ * operations. It is important to note that these timeouts are not part of the MySQL protocol, and rather timeout | ||
* This overrides the same option set at the connection level. | ||
* | ||
* | ||
*/ | ||
rowsAsArray?: boolean | ||
/** | ||
* By specifying a function that returns a readable stream, an arbitrary stream can be sent when sending a local fs file. | ||
*/ | ||
infileStreamFactory?: (path: string) => Readable; | ||
} | ||
@@ -131,3 +141,3 @@ | ||
*/ | ||
stream(options: Query.StreamOptions): Readable; | ||
stream(options?: Query.StreamOptions): Readable; | ||
@@ -134,0 +144,0 @@ on(event: string, listener: Function): this; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
476547
99
12026
286
11
21
2
2
+ Added@types/chai@^4.3.3
+ Addedchai@^4.3.6
+ Addedmocha@^10.0.0
+ Added@types/chai@4.3.19(transitive)
+ Addedansi-colors@4.1.3(transitive)
+ Addedansi-regex@5.0.1(transitive)
+ Addedansi-styles@4.3.0(transitive)
+ Addedanymatch@3.1.3(transitive)
+ Addedargparse@2.0.1(transitive)
+ Addedassertion-error@1.1.0(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbinary-extensions@2.3.0(transitive)
+ Addedbrace-expansion@2.0.1(transitive)
+ Addedbraces@3.0.3(transitive)
+ Addedbrowser-stdout@1.3.1(transitive)
+ Addedcamelcase@6.3.0(transitive)
+ Addedchai@4.5.0(transitive)
+ Addedchalk@4.1.2(transitive)
+ Addedcheck-error@1.0.3(transitive)
+ Addedchokidar@3.6.0(transitive)
+ Addedcliui@7.0.4(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addeddecamelize@4.0.0(transitive)
+ Addeddeep-eql@4.1.4(transitive)
+ Addeddiff@5.2.0(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addedescalade@3.2.0(transitive)
+ Addedescape-string-regexp@4.0.0(transitive)
+ Addedfill-range@7.1.1(transitive)
+ Addedfind-up@5.0.0(transitive)
+ Addedflat@5.0.2(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfsevents@2.3.3(transitive)
+ Addedget-caller-file@2.0.5(transitive)
+ Addedget-func-name@2.0.2(transitive)
+ Addedglob@8.1.0(transitive)
+ Addedglob-parent@5.1.2(transitive)
+ Addedhas-flag@4.0.0(transitive)
+ Addedhe@1.2.0(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-binary-path@2.1.0(transitive)
+ Addedis-extglob@2.1.1(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedis-glob@4.0.3(transitive)
+ Addedis-number@7.0.0(transitive)
+ Addedis-plain-obj@2.1.0(transitive)
+ Addedis-unicode-supported@0.1.0(transitive)
+ Addedjs-yaml@4.1.0(transitive)
+ Addedlocate-path@6.0.0(transitive)
+ Addedlog-symbols@4.1.0(transitive)
+ Addedloupe@2.3.7(transitive)
+ Addedminimatch@5.1.6(transitive)
+ Addedmocha@10.7.3(transitive)
+ Addedms@2.1.3(transitive)
+ Addednormalize-path@3.0.0(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedp-limit@3.1.0(transitive)
+ Addedp-locate@5.0.0(transitive)
+ Addedpath-exists@4.0.0(transitive)
+ Addedpathval@1.1.1(transitive)
+ Addedpicomatch@2.3.1(transitive)
+ Addedrandombytes@2.1.0(transitive)
+ Addedreaddirp@3.6.0(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedserialize-javascript@6.0.2(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedstrip-json-comments@3.1.1(transitive)
+ Addedsupports-color@7.2.08.1.1(transitive)
+ Addedto-regex-range@5.0.1(transitive)
+ Addedtype-detect@4.1.0(transitive)
+ Addedworkerpool@6.5.1(transitive)
+ Addedwrap-ansi@7.0.0(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedy18n@5.0.8(transitive)
+ Addedyargs@16.2.0(transitive)
+ Addedyargs-parser@20.2.9(transitive)
+ Addedyargs-unparser@2.0.0(transitive)
+ Addedyocto-queue@0.1.0(transitive)