diff --git a/lib/cmd/batch-bulk.js b/lib/cmd/batch-bulk.js index 4e1a669e..61673dce 100644 --- a/lib/cmd/batch-bulk.js +++ b/lib/cmd/batch-bulk.js @@ -30,6 +30,7 @@ class BatchBulk extends CommonBinary { if (this.opts.timeout) { const err = Errors.createError( 'Cannot use timeout for Batch statement', + this.sql, false, info, 'HY000', @@ -112,10 +113,10 @@ class BatchBulk extends CommonBinary { displaySql() { if (this.opts && this.initialValues) { if (this.sql.length > this.opts.debugLen) { - return 'sql: ' + this.sql.substring(0, this.opts.debugLen) + '...'; + return this.sql.substring(0, this.opts.debugLen) + '...'; } - let sqlMsg = 'sql: ' + this.sql + ' - parameters:'; + let sqlMsg = this.sql + ' - parameters:'; sqlMsg += '['; for (let i = 0; i < this.initialValues.length; i++) { if (i !== 0) sqlMsg += ','; @@ -129,7 +130,7 @@ class BatchBulk extends CommonBinary { sqlMsg += ']'; return sqlMsg; } - return 'sql: ' + this.sql + ' - parameters:[]'; + return this.sql + ' - parameters:[]'; } success(val) { @@ -202,6 +203,7 @@ class BatchBulk extends CommonBinary { if (this.stack) { err = Errors.createError( err.message, + this.sql, err.fatal, info, err.sqlState, diff --git a/lib/cmd/batch-rewrite.js b/lib/cmd/batch-rewrite.js index 51743824..1c5c77cd 100644 --- a/lib/cmd/batch-rewrite.js +++ b/lib/cmd/batch-rewrite.js @@ -28,6 +28,7 @@ class BatchRewrite extends CommonText { if (this.opts.timeout) { const err = Errors.createError( 'Cannot use timeout for Batch statement', + this.sql, false, info, 'HY000', @@ -207,6 +208,7 @@ class BatchRewrite extends CommonText { if (this.stack) { err = Errors.createError( err.message, + this.sql, err.fatal, info, err.sqlState, diff --git a/lib/cmd/command.js b/lib/cmd/command.js index bb86d249..0e9c1c4c 100644 --- a/lib/cmd/command.js +++ b/lib/cmd/command.js @@ -20,7 +20,9 @@ class Command extends EventEmitter { this.sending = false; } - displaySql() {} + displaySql() { + return null; + } /** * Throw an an unexpected error. @@ -36,7 +38,7 @@ class Command extends EventEmitter { if (this.reject) { process.nextTick( this.reject, - Errors.createError(msg, fatal, info, sqlState, errno, this.stack, false) + Errors.createError(msg, this.displaySql(), fatal, info, sqlState, errno, this.stack, false) ); this.resolve = null; this.reject = null; @@ -58,7 +60,7 @@ class Command extends EventEmitter { if (this.reject) { process.nextTick( this.reject, - Errors.createError(msg, fatal, info, sqlState, errno, this.stack, false) + Errors.createError(msg, this.displaySql(), fatal, info, sqlState, errno, this.stack, false) ); this.resolve = null; this.reject = null; @@ -79,6 +81,7 @@ class Command extends EventEmitter { if (this.stack) { err = Errors.createError( err.message, + err.sql, err.fatal, info, err.sqlState, diff --git a/lib/cmd/handshake/auth/caching-sha2-password-auth.js b/lib/cmd/handshake/auth/caching-sha2-password-auth.js index 598296d7..f87ad1d7 100644 --- a/lib/cmd/handshake/auth/caching-sha2-password-auth.js +++ b/lib/cmd/handshake/auth/caching-sha2-password-auth.js @@ -89,6 +89,7 @@ class CachingSha2PasswordAuth extends PluginAuth { 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`', + null, true, info, '08S01', diff --git a/lib/cmd/handshake/auth/ed25519-password-auth.js b/lib/cmd/handshake/auth/ed25519-password-auth.js index 14d6c7d8..b3658fc4 100644 --- a/lib/cmd/handshake/auth/ed25519-password-auth.js +++ b/lib/cmd/handshake/auth/ed25519-password-auth.js @@ -93,93 +93,21 @@ const gf = function (init) { const gf0 = gf(), gf1 = gf([1]), D2 = gf([ - 0xf159, - 0x26b2, - 0x9b94, - 0xebd6, - 0xb156, - 0x8283, - 0x149a, - 0x00e0, - 0xd130, - 0xeef3, - 0x80f2, - 0x198e, - 0xfce7, - 0x56df, - 0xd9dc, - 0x2406 + 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 + 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 + 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 + 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) { diff --git a/lib/cmd/handshake/auth/sha256-password-auth.js b/lib/cmd/handshake/auth/sha256-password-auth.js index 52291495..a2e11780 100644 --- a/lib/cmd/handshake/auth/sha256-password-auth.js +++ b/lib/cmd/handshake/auth/sha256-password-auth.js @@ -54,7 +54,7 @@ class Sha256PasswordAuth extends PluginAuth { 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`', - + null, true, info, '08S01', diff --git a/lib/cmd/handshake/handshake.js b/lib/cmd/handshake/handshake.js index fa3794ab..9f3e1085 100644 --- a/lib/cmd/handshake/handshake.js +++ b/lib/cmd/handshake/handshake.js @@ -192,6 +192,7 @@ class Handshake extends Command { "Client does not support authentication protocol '" + pluginName + "' requested by server. ", + null, true, info, '08004', @@ -237,6 +238,7 @@ class Handshake extends Command { if (!Handshake.ensureNodeVersion(11, 6, 0)) { throw Errors.createError( 'sha256_password authentication plugin require node 11.6+', + null, true, info, '08004', @@ -250,6 +252,7 @@ class Handshake extends Command { if (!Handshake.ensureNodeVersion(11, 6, 0)) { throw Errors.createError( 'caching_sha2_password authentication plugin require node 11.6+', + null, true, info, '08004', diff --git a/lib/cmd/query.js b/lib/cmd/query.js index d2ee13e8..f5ff4697 100644 --- a/lib/cmd/query.js +++ b/lib/cmd/query.js @@ -123,6 +123,7 @@ class Query extends CommonText { const err = Errors.createError( 'Cannot use timeout for MariaDB server before 10.1.2. timeout value: ' + this.opts.timeout, + this.sql, false, info, 'HY000', @@ -137,6 +138,7 @@ class Query extends CommonText { // 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, + this.sql, false, info, 'HY000', @@ -161,7 +163,7 @@ class Query extends CommonText { 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(), + 'Parameter at position ' + (this.values.length + 1) + ' is not set', false, info, 'HY000', diff --git a/lib/cmd/resultset.js b/lib/cmd/resultset.js index a0ad8c6b..41bbb302 100644 --- a/lib/cmd/resultset.js +++ b/lib/cmd/resultset.js @@ -448,13 +448,13 @@ class ResultSet extends Command { displaySql() { if (this.opts && this.initialValues) { if (this.sql.length > this.opts.debugLen) { - return 'sql: ' + this.sql.substring(0, this.opts.debugLen) + '...'; + return this.sql.substring(0, this.opts.debugLen) + '...'; } - let sqlMsg = 'sql: ' + this.sql + ' - parameters:'; + let sqlMsg = this.sql + ' - parameters:'; return this.logParameters(sqlMsg, this.initialValues); } - return 'sql: ' + this.sql + ' - parameters:[]'; + return this.sql + ' - parameters:[]'; } logParameters(sqlMsg, values) { @@ -513,6 +513,7 @@ class ResultSet extends Command { "' doesn't correspond to query " + this.sql + '. Query cancelled. Check for malicious server / proxy', + this.sql, false, info, '45034', @@ -532,6 +533,7 @@ class ResultSet extends Command { out.writeEmptyPacket(); const error = Errors.createError( 'LOCAL INFILE command failed: ' + err.message, + this.sql, false, info, '22000', diff --git a/lib/config/connection-options.js b/lib/config/connection-options.js index d8078357..48019d05 100644 --- a/lib/config/connection-options.js +++ b/lib/config/connection-options.js @@ -137,6 +137,7 @@ class ConnectionOptions { if (!moment.tz.zone(tzName)) { throw Errors.createError( "Unknown IANA timezone '" + tzName + "'.", + null, true, null, '08S01', diff --git a/lib/connection-callback.js b/lib/connection-callback.js index 56d4c8c6..efda6365 100644 --- a/lib/connection-callback.js +++ b/lib/connection-callback.js @@ -79,6 +79,7 @@ function ConnectionCallback(options) { if (!callback) { throw new Errors.createError( 'missing callback parameter', + null, false, this.info, 'HY000', @@ -95,6 +96,7 @@ function ConnectionCallback(options) { callback( Errors.createError( 'Connection closed', + null, true, this.info, '08S01', diff --git a/lib/connection.js b/lib/connection.js index eb118830..43e9abc5 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -62,6 +62,7 @@ function Connection(options) { return Promise.reject( Errors.createError( 'Connection closed', + null, true, info, '08S01', @@ -74,6 +75,7 @@ function Connection(options) { return Promise.reject( Errors.createError( 'Connection is already connecting', + null, true, info, '08S01', @@ -98,6 +100,7 @@ function Connection(options) { return Promise.reject( Errors.createError( 'method changeUser not available for MySQL server due to Bug #83472', + null, false, info, '0A000', @@ -198,7 +201,8 @@ function Connection(options) { if (!_values) { return Promise.reject( Errors.createError( - 'Batch must have values set\nsql: ' + _sql + ' - parameters:[]', + 'Batch must have values set', + _sql, false, info, 'HY000', @@ -259,6 +263,7 @@ function Connection(options) { reject( Errors.createError( 'Ping cannot have negative timeout value', + null, false, info, '0A000', @@ -268,7 +273,9 @@ function Connection(options) { return; } const tOut = setTimeout(() => { - reject(Errors.createError('Ping timeout', true, info, '0A000', Errors.ER_PING_TIMEOUT)); + reject( + Errors.createError('Ping timeout', null, true, info, '0A000', Errors.ER_PING_TIMEOUT) + ); // close connection _addCommand = _addCommandDisabled; clearTimeout(_timeout); @@ -399,6 +406,7 @@ function Connection(options) { const killResHandler = () => { const destroyError = Errors.createError( 'Connection destroyed, command was killed', + null, true, info, '08S01', @@ -455,6 +463,7 @@ function Connection(options) { this.format = (sql, values) => { throw Errors.createError( '"Connection.format intentionally not implemented. please use Connection.query(sql, values), it will be more secure and faster', + null, false, info, '0A000', @@ -610,7 +619,8 @@ function Connection(options) { if (_cb) { _cb( Errors.createError( - 'Batch must have values set\nsql: ' + _sql + ' - parameters:[]', + 'Batch must have values set', + _sql, false, info, 'HY000', @@ -761,6 +771,7 @@ function Connection(options) { JSON.stringify(opts.sessionVariables) + '). Error: ' + initialErr.message, + sessionQuery, true, info, '08S01', @@ -803,6 +814,7 @@ function Connection(options) { "Automatic timezone setting fails. Server timezone '" + serverTimezone + "' does't have a corresponding IANA timezone. Option timezone must be set according to server timezone", + null, true, info, '08S01', @@ -860,6 +872,7 @@ function Connection(options) { return Promise.reject( Errors.createError( 'Error executing initial sql command: ' + initialErr.message, + null, true, info, '08S01', @@ -875,25 +888,26 @@ function Connection(options) { const _executeSessionTimeout = () => { if (opts.queryTimeout) { if (info.isMariaDB() && info.hasMinVersion(10, 1, 2)) { - this._queryPromise('SET max_statement_time=' + opts.queryTimeout / 1000).catch( - (initialErr) => { - return Promise.reject( - Errors.createError( - 'Error setting session queryTimeout: ' + initialErr.message, - true, - info, - '08S01', - Errors.ER_INITIAL_TIMEOUT_ERROR, - null - ) - ); - } - ); + const query = 'SET max_statement_time=' + opts.queryTimeout / 1000; + this._queryPromise(query).catch((initialErr) => { + return Promise.reject( + Errors.createError( + 'Error setting session queryTimeout: ' + initialErr.message, + query, + true, + info, + '08S01', + Errors.ER_INITIAL_TIMEOUT_ERROR, + null + ) + ); + }); } else { return Promise.reject( Errors.createError( 'Can only use queryTimeout for MariaDB server after 10.1.1. queryTimeout value: ' + - opts.queryTimeout, + null, + opts.queryTimeout, false, info, 'HY000', @@ -1084,6 +1098,7 @@ function Connection(options) { packet.end + ')\n' + Utils.log(opts, packet.buf, packet.pos, packet.end), + null, true, info, '08S01', @@ -1106,7 +1121,8 @@ function Connection(options) { if (_status === Status.CLOSING || _status === Status.CLOSED) { return Promise.reject( Errors.createError( - 'Cannot execute new commands: connection closed\nsql: ' + sql, + 'Cannot execute new commands: connection closed', + sql, true, info, '08S01', @@ -1140,6 +1156,7 @@ function Connection(options) { 'Connection timeout: failed to create socket after ' + (Date.now() - initialConnectionTime) + 'ms', + null, true, info, '08S01', @@ -1155,7 +1172,14 @@ function Connection(options) { * @private */ const _socketTimeoutReached = function () { - const err = Errors.createError('socket timeout', true, info, '08S01', Errors.ER_SOCKET_TIMEOUT); + const err = Errors.createError( + 'socket timeout', + null, + true, + info, + '08S01', + Errors.ER_SOCKET_TIMEOUT + ); const packetMsgs = info.getLastPackets(); if (packetMsgs !== '') { err.message = err.message + '\nlast received packets:\n' + packetMsgs; @@ -1239,7 +1263,7 @@ function Connection(options) { */ const _addCommandDisabled = (cmd) => { cmd.throwNewError( - 'Cannot execute new commands: connection closed\n' + cmd.displaySql(), + 'Cannot execute new commands: connection closed', true, info, '08S01', @@ -1265,6 +1289,7 @@ function Connection(options) { if (!err) { err = Errors.createError( 'socket has unexpectedly been closed', + null, true, info, '08S01', diff --git a/lib/io/packet.js b/lib/io/packet.js index 493cc571..b05aaa8d 100644 --- a/lib/io/packet.js +++ b/lib/io/packet.js @@ -488,13 +488,13 @@ class Packet { } 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, + sql, fatal, info, sqlState, @@ -502,7 +502,7 @@ class Packet { stack ); } - return Errors.createError(msg, fatal, info, sqlState, errorCode, stack); + return Errors.createError(msg, sql, fatal, info, sqlState, errorCode, stack); } } diff --git a/lib/misc/errors.js b/lib/misc/errors.js index f45fc82a..26619ada 100644 --- a/lib/misc/errors.js +++ b/lib/misc/errors.js @@ -2,7 +2,7 @@ const ErrorCodes = require('../const/error-code'); class SqlError extends Error { - constructor(msg, fatal, info, sqlState, errno, additionalStack, addHeader) { + constructor(msg, sql, fatal, info, sqlState, errno, additionalStack, addHeader) { super( (addHeader === undefined || addHeader ? '(conn=' + @@ -12,9 +12,12 @@ class SqlError extends Error { ', SQLState: ' + (sqlState ? sqlState : 'HY000') + ') ' - : '') + msg + : '') + + msg + + (sql ? '\nsql: ' + sql : '') ); - this.msg = msg; + this.text = msg; + this.sql = sql; this.fatal = fatal; this.errno = errno; this.sqlState = sqlState; @@ -36,6 +39,7 @@ class SqlError extends Error { * Error factory, so error get connection information. * * @param msg current error message + * @param sql sql command * @param fatal is error fatal * @param info connection information * @param sqlState sql state @@ -46,6 +50,7 @@ class SqlError extends Error { */ module.exports.createError = function ( msg, + sql, fatal, info, sqlState, @@ -53,7 +58,7 @@ module.exports.createError = function ( additionalStack, addHeader ) { - return new SqlError(msg, fatal, info, sqlState, errno, additionalStack, addHeader); + return new SqlError(msg, sql, fatal, info, sqlState, errno, additionalStack, addHeader); }; /******************************************************************************** diff --git a/lib/misc/parse.js b/lib/misc/parse.js index 0c5a3337..3b680d8d 100644 --- a/lib/misc/parse.js +++ b/lib/misc/parse.js @@ -214,7 +214,8 @@ module.exports.splitQueryPlaceholder = function (sql, info, initialValues, displ const val = initialValues[placeholderName]; if (val === undefined) { throw Errors.createError( - "Placeholder '" + placeholderName + "' is not defined\n" + displaySql.call(), + "Placeholder '" + placeholderName + "' is not defined", + displaySql.call(), false, info, 'HY000', diff --git a/lib/misc/utils.js b/lib/misc/utils.js index ace3bfc2..18eab80d 100644 --- a/lib/misc/utils.js +++ b/lib/misc/utils.js @@ -91,6 +91,7 @@ module.exports.escapeId = (opts, info, value) => { if (!value || value === '') { throw Errors.createError( 'Cannot escape empty ID value', + null, false, info, '0A000', @@ -100,6 +101,7 @@ module.exports.escapeId = (opts, info, value) => { if (value.includes('\u0000')) { throw Errors.createError( 'Cannot escape ID with null character (u0000)', + null, false, info, '0A000', diff --git a/lib/pool-base.js b/lib/pool-base.js index 379aa365..c0cf8a52 100644 --- a/lib/pool-base.js +++ b/lib/pool-base.js @@ -54,6 +54,7 @@ function PoolBase(options, processTask, createConnectionPool, pingPromise) { return Promise.reject( Errors.createError( 'pool is already closed', + null, false, null, 'HY000', @@ -80,6 +81,7 @@ function PoolBase(options, processTask, createConnectionPool, pingPromise) { let task; const err = Errors.createError( 'pool is ending, connection request aborted', + null, false, null, 'HY000', @@ -209,6 +211,7 @@ function PoolBase(options, processTask, createConnectionPool, pingPromise) { return Promise.reject( Errors.createError( 'pool is closed', + null, false, null, 'HY000', @@ -301,6 +304,7 @@ function PoolBase(options, processTask, createConnectionPool, pingPromise) { 'retrieve connection from pool timeout after ' + Math.abs(Date.now() - (task.timeout - opts.acquireTimeout)) + 'ms', + null, false, null, 'HY000', @@ -339,6 +343,7 @@ function PoolBase(options, processTask, createConnectionPool, pingPromise) { reject( Errors.createError( 'Cannot create new connection to pool, pool closed', + null, true, null, '08S01', diff --git a/lib/pool-callback.js b/lib/pool-callback.js index ffe47705..23634e0f 100644 --- a/lib/pool-callback.js +++ b/lib/pool-callback.js @@ -47,6 +47,7 @@ function PoolCallback(options) { reject( Errors.createError( 'Cannot create new connection to pool, pool closed', + null, true, null, '08S01', diff --git a/lib/pool-promise.js b/lib/pool-promise.js index 5aed61ac..5b557f24 100644 --- a/lib/pool-promise.js +++ b/lib/pool-promise.js @@ -38,6 +38,7 @@ function PoolPromise(options) { return Promise.reject( Errors.createError( 'Cannot create new connection to pool, pool closed', + null, true, null, '08S01', diff --git a/test/integration/datatype/test-boolean.js b/test/integration/datatype/test-boolean.js index c3c96265..3631848a 100644 --- a/test/integration/datatype/test-boolean.js +++ b/test/integration/datatype/test-boolean.js @@ -1,5 +1,6 @@ 'use strict'; +const base = require('../../base'); const { assert } = require('chai'); describe('boolean type', () => { diff --git a/test/integration/test-connection-opts.js b/test/integration/test-connection-opts.js index c88d24ee..b6c5c6c6 100644 --- a/test/integration/test-connection-opts.js +++ b/test/integration/test-connection-opts.js @@ -442,8 +442,7 @@ describe('connection option', () => { conn .query({ timeout: 1000, - sql: - 'SELECT 1;select c1.* from information_schema.columns as c1, information_schema.tables, information_schema.tables as t2' + sql: 'SELECT 1;select c1.* from information_schema.columns as c1, information_schema.tables, information_schema.tables as t2' }) .then(() => { conn.end(); diff --git a/test/integration/test-error.js b/test/integration/test-error.js index 252b1df1..0e8fc028 100644 --- a/test/integration/test-error.js +++ b/test/integration/test-error.js @@ -131,8 +131,11 @@ describe('Error', () => { } else { assert.isTrue(err.message.includes('You have an error in your SQL syntax')); assert.isTrue( - err.message.includes("sql: wrong query ?, ? - parameters:[123456789,'long par...]") + err.message.includes( + "sql: wrong query ?, ? - parameters:[123456789,'long paramete...]" + ) ); + assert.equal(err.sql, "wrong query ?, ? - parameters:[123456789,'long paramete...]"); assert.equal(err.errno, 1064); assert.equal(err.sqlState, 42000); assert.equal(err.code, 'ER_PARSE_ERROR'); @@ -216,16 +219,26 @@ describe('Error', () => { 'Query could not be tokenized and will hence be rejected. Please ensure that the SQL syntax is correct.' ) ); + assert.isTrue( + err.text.includes( + 'Query could not be tokenized and will hence be rejected. Please ensure that the SQL syntax is correct.' + ) + ); assert.equal(err.sqlState, 'HY000'); } else { assert.isTrue(err.message.includes('You have an error in your SQL syntax')); + assert.isTrue(err.text.includes('You have an error in your SQL syntax')); assert.equal(err.errno, 1064); assert.equal(err.sqlState, 42000); assert.equal(err.code, 'ER_PARSE_ERROR'); } assert.isTrue( - err.message.includes("sql: wrong query :par1, :par2 - parameters:{'par1':'som...}") + err.message.includes( + "sql: wrong query :par1, :par2 - parameters:{'par1':'some par...}" + ) ); + assert.equal(err.sql, "wrong query :par1, :par2 - parameters:{'par1':'some par...}"); + conn.end(); done(); }); @@ -283,6 +296,7 @@ describe('Error', () => { assert.isTrue(err != null); assert.isTrue(err.message.includes('Cannot execute new commands: connection closed')); assert.isTrue(err.message.includes('sql: DO 1 - parameters:[]')); + assert.equal(err.sql, 'DO 1 - parameters:[]'); assert.isTrue(err.fatal); assert.equal(err.sqlState, '08S01'); assert.equal(err.code, 'ER_CMD_CONNECTION_CLOSED'); @@ -334,7 +348,7 @@ describe('Error', () => { it('server close connection without warning', function (done) { //removed for maxscale, since wait_timeout will be set to other connections - if (process.env.MAXSCALE_TEST_DISABLE) this.skip(); + if (process.env.srv === 'maxscale' || process.env.srv === 'skysql-ha') this.skip(); this.timeout(20000); let connectionErr = false; base @@ -374,7 +388,11 @@ describe('Error', () => { it('server close connection - no connection error event', function (done) { this.timeout(20000); - if (process.env.MAXSCALE_TEST_DISABLE || process.env.SKYSQL || process.env.SKYSQL_HA) + if ( + process.env.srv === 'maxscale' || + process.env.srv === 'skysql' || + process.env.srv === 'skysql-ha' + ) this.skip(); // Remove Mocha's error listener const originalException = process.listeners('uncaughtException').pop(); @@ -416,7 +434,11 @@ describe('Error', () => { }); it('server close connection during query', function (done) { - if (process.env.SKYSQL || process.env.MAXSCALE_TEST_DISABLE || process.env.SKYSQL_HA) + if ( + process.env.srv === 'maxscale' || + process.env.srv === 'skysql' || + process.env.srv === 'skysql-ha' + ) this.skip(); this.timeout(20000); base @@ -429,7 +451,7 @@ describe('Error', () => { done(new Error('must have thrown error !')); }) .catch((err) => { - if (process.env.MAXSCALE_TEST_DISABLE) { + if (process.env.srv === 'maxscale' || process.env.srv === 'skysql-ha') { assert.isTrue(err.message.includes('Lost connection to backend server'), err.message); assert.equal(err.sqlState, 'HY000'); } else { @@ -450,7 +472,7 @@ describe('Error', () => { }); it('end connection query error', function (done) { - if (process.env.MAXSCALE_TEST_DISABLE) this.skip(); + if (process.env.srv === 'maxscale' || process.env.srv === 'skysql-ha') this.skip(); base .createConnection() .then((conn) => { @@ -502,9 +524,9 @@ describe('Error', () => { .catch(handleResult); shareConn - .query('SELECT 1') + .query("SELECT '1'") .then((rows) => { - assert.deepEqual(rows, [{ 1: 1 }]); + assert.deepEqual(rows, [{ 1: '1' }]); done(); }) .catch(done); @@ -541,9 +563,9 @@ describe('Error', () => { .catch(handleResult); shareConn - .query('SELECT 1') + .query("SELECT '1'") .then((rows) => { - assert.deepEqual(rows, [{ 1: 1 }]); + assert.deepEqual(rows, [{ 1: '1' }]); done(); }) .catch(done); @@ -575,9 +597,9 @@ describe('Error', () => { }) .catch(handleResult); shareConn - .query('SELECT 1') + .query("SELECT '1'") .then((rows) => { - assert.deepEqual(rows, [{ 1: 1 }]); + assert.deepEqual(rows, [{ 1: '1' }]); done(); }) .catch(done); @@ -599,6 +621,7 @@ describe('Error', () => { done(new Error('must have thrown error !')); }) .catch((err) => { + console.log(err); assert.equal(err.errno, 45016); assert.equal(err.sqlState, 'HY000'); assert.equal(err.code, 'ER_MISSING_PARAMETER'); @@ -610,9 +633,9 @@ describe('Error', () => { ) ); return conn - .query('SELECT 1') + .query("SELECT '1'") .then((rows) => { - assert.deepEqual(rows, [{ 1: 1 }]); + assert.deepEqual(rows, [{ 1: '1' }]); conn.end(); done(); }) @@ -647,9 +670,9 @@ describe('Error', () => { ); }); shareConn - .query('SELECT 1') + .query("SELECT '1'") .then((rows) => { - assert.deepEqual(rows, [{ 1: 1 }]); + assert.deepEqual(rows, [{ 1: '1' }]); done(); }) .catch(done); diff --git a/test/integration/test-placholders.js b/test/integration/test-placholders.js index b6bdf15d..ea3cdd3d 100644 --- a/test/integration/test-placholders.js +++ b/test/integration/test-placholders.js @@ -107,6 +107,11 @@ describe('Placeholder', () => { assert.equal(err.errno, 45018); assert.equal(err.code, 'ER_PLACEHOLDER_UNDEFINED'); assert.equal(err.sqlState, 'HY000'); + assert.equal(err.text, "Placeholder 'param2' is not defined"); + assert.equal( + err.sql, + "INSERT INTO undefinedParameter values (:param3, :param1, :param2) - parameters:{'param1':1,'param3':3,'param4':4}" + ); assert(!err.fatal); assert.ok( err.message.includes( diff --git a/test/unit/io/test-packet.js b/test/unit/io/test-packet.js index 6ebe4894..5da269f0 100644 --- a/test/unit/io/test-packet.js +++ b/test/unit/io/test-packet.js @@ -8,22 +8,7 @@ describe('packet', () => { const head = Buffer.from([0xaa, 0xbb, 0xcc, 0x33]); const buf = Buffer.from([0xf0, 0x9f, 0xa4, 0x98, 0xf0, 0x9f, 0x92, 0xaa]); // 🤘💪 const longbuf = Buffer.from([ - 0x00, - 0x01, - 0x02, - 0x03, - 0x04, - 0x05, - 0x06, - 0x07, - 0x08, - 0x09, - 0x0a, - 0x0b, - 0x0c, - 0x0d, - 0x0e, - 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 ]); diff --git a/test/unit/misc/test-parse.js b/test/unit/misc/test-parse.js index 8c245120..62aa2039 100644 --- a/test/unit/misc/test-parse.js +++ b/test/unit/misc/test-parse.js @@ -34,8 +34,7 @@ describe('parse', () => { values ); assert.deepEqual(res, { - sql: - 'INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ?, 5, ?, 8) ON DUPLICATE KEY UPDATE col2=col2+10', + sql: 'INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ?, 5, ?, 8) ON DUPLICATE KEY UPDATE col2=col2+10', values: [ [2, 1], [4, null], @@ -76,8 +75,7 @@ describe('parse', () => { values ); assert.deepEqual(res, { - sql: - 'INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ?, 5, ?, 8) ON DUPLICATE KEY UPDATE col2=?', + sql: 'INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ?, 5, ?, 8) ON DUPLICATE KEY UPDATE col2=?', values: [ [2, 1, null], [4, null, 3], diff --git a/test/unit/misc/test-utils.js b/test/unit/misc/test-utils.js index d8de627c..e540a569 100644 --- a/test/unit/misc/test-utils.js +++ b/test/unit/misc/test-utils.js @@ -8,22 +8,7 @@ describe('utils', () => { const head = Buffer.from([0xaa, 0xbb, 0xcc, 0x33]); const buf = Buffer.from([0xf0, 0x9f, 0xa4, 0x98, 0xf0, 0x9f, 0x92, 0xaa]); // 🤘💪 const longbuf = Buffer.from([ - 0x00, - 0x01, - 0x02, - 0x03, - 0x04, - 0x05, - 0x06, - 0x07, - 0x08, - 0x09, - 0x0a, - 0x0b, - 0x0c, - 0x0d, - 0x0e, - 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 ]); diff --git a/types/index.d.ts b/types/index.d.ts index 59241590..23e6041b 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -678,11 +678,16 @@ export interface SqlError extends Error { * (e.g. 'PROTOCOL_CONNECTION_LOST'). */ code: string | null; - + + /** + * original error message value + */ + text: string | null; + /** - * The message text and information (e.g conn=5149, no: 1644, SQLState: 45000) for better identification + * The sql command associate */ - msg: string | null; + sql: string | null; /** * The error number for the error code