Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 5 additions & 20 deletions lib/promise/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const EventEmitter = require('events').EventEmitter;
const PromisePreparedStatementInfo = require('./prepared_statement_info.js');
const makeDoneCb = require('./make_done_cb.js');
const { assignError } = makeDoneCb;
const inheritEvents = require('./inherit_events.js');
const BaseConnection = require('../base/connection.js');

Expand Down Expand Up @@ -105,11 +106,7 @@ class PromiseConnection extends EventEmitter {
return new this.Promise((resolve, reject) => {
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;
assignError(localErr, err);
reject(localErr);
} else {
resolve(true);
Expand All @@ -124,11 +121,7 @@ class PromiseConnection extends EventEmitter {
return new this.Promise((resolve, reject) => {
c.connect((err, param) => {
if (err) {
localErr.message = err.message;
localErr.code = err.code;
localErr.errno = err.errno;
localErr.sqlState = err.sqlState;
localErr.sqlMessage = err.sqlMessage;
assignError(localErr, err);
reject(localErr);
} else {
resolve(param);
Expand All @@ -144,11 +137,7 @@ class PromiseConnection extends EventEmitter {
return new this.Promise((resolve, reject) => {
c.prepare(options, (err, statement) => {
if (err) {
localErr.message = err.message;
localErr.code = err.code;
localErr.errno = err.errno;
localErr.sqlState = err.sqlState;
localErr.sqlMessage = err.sqlMessage;
assignError(localErr, err);
reject(localErr);
} else {
const wrappedStatement = new PromisePreparedStatementInfo(
Expand All @@ -167,11 +156,7 @@ class PromiseConnection extends EventEmitter {
return new this.Promise((resolve, reject) => {
c.changeUser(options, (err) => {
if (err) {
localErr.message = err.message;
localErr.code = err.code;
localErr.errno = err.errno;
localErr.sqlState = err.sqlState;
localErr.sqlMessage = err.sqlMessage;
assignError(localErr, err);
reject(localErr);
} else {
resolve();
Expand Down
18 changes: 12 additions & 6 deletions lib/promise/make_done_cb.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
'use strict';

function assignError(localErr, err) {
localErr.message = err.message;
localErr.code = err.code;
localErr.errno = err.errno;
localErr.fatal = err.fatal;
localErr.sql = err.sql;
localErr.sqlState = err.sqlState;
localErr.sqlMessage = err.sqlMessage;
}

function makeDoneCb(resolve, reject, localErr) {
return function (err, rows, fields) {
if (err) {
localErr.message = err.message;
localErr.code = err.code;
localErr.errno = err.errno;
localErr.sql = err.sql;
localErr.sqlState = err.sqlState;
localErr.sqlMessage = err.sqlMessage;
assignError(localErr, err);
reject(localErr);
} else {
resolve([rows, fields]);
Expand All @@ -17,3 +22,4 @@ function makeDoneCb(resolve, reject, localErr) {
}

module.exports = makeDoneCb;
module.exports.assignError = assignError;
9 changes: 3 additions & 6 deletions lib/promise/pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const EventEmitter = require('events').EventEmitter;
const makeDoneCb = require('./make_done_cb.js');
const { assignError } = makeDoneCb;
const PromisePoolConnection = require('./pool_connection.js');
const inheritEvents = require('./inherit_events.js');
const BasePool = require('../base/pool.js');
Expand Down Expand Up @@ -59,7 +60,7 @@ class PromisePool extends EventEmitter {
}
return new this.Promise((resolve, reject) => {
const done = makeDoneCb(resolve, reject, localErr);
if (args) {
if (args !== undefined) {
corePool.execute(sql, args, done);
} else {
corePool.execute(sql, done);
Expand All @@ -73,11 +74,7 @@ class PromisePool extends EventEmitter {
return new this.Promise((resolve, reject) => {
corePool.end((err) => {
if (err) {
localErr.message = err.message;
localErr.code = err.code;
localErr.errno = err.errno;
localErr.sqlState = err.sqlState;
localErr.sqlMessage = err.sqlMessage;
assignError(localErr, err);
reject(localErr);
} else {
resolve();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { describe, it, strict } from 'poku';
import { createConnection } from '../../common.test.mjs';

type MysqlError = Error & {
code?: string;
errno?: number;
fatal?: boolean;
sqlState?: string;
sqlMessage?: string;
};

await describe('promise error propagation: fatal flag in connection methods', async () => {
await it('ping rejection should carry fatal flag', async () => {
// Connect to an invalid host so ping fails with a fatal error
const conn = createConnection({ host: '127.0.0.1', port: 1 }).promise();

let caughtErr: MysqlError | undefined;
try {
await conn.ping();
} catch (err) {
caughtErr = err as MysqlError;
}

strict.ok(caughtErr, 'Expected ping to throw');
strict.ok('code' in caughtErr!, 'code should be propagated');
strict.equal(
caughtErr!.fatal,
true,
'fatal should be true for connection errors'
);
});

await it('connect rejection should carry fatal flag', async () => {
const conn = createConnection({ host: '127.0.0.1', port: 1 }).promise();

let caughtErr: MysqlError | undefined;
try {
await conn.connect();
} catch (err) {
caughtErr = err as MysqlError;
}

strict.ok(caughtErr, 'Expected connect to throw');
strict.ok('code' in caughtErr!, 'code should be propagated');
strict.equal(
caughtErr!.fatal,
true,
'fatal should be true for connection errors'
);
});
});

await describe('promise error propagation: fatal flag in prepare and changeUser', async () => {
const conn = createConnection().promise();

await it('prepare rejection should propagate error properties', async () => {
let caughtErr: MysqlError | undefined;
try {
await conn.prepare('SELECT * FROM nonexistent_table_xyz_abc');
} catch (err) {
caughtErr = err as MysqlError;
}
strict.ok(caughtErr, 'Expected prepare to throw');
strict.ok('errno' in caughtErr!, 'errno should be propagated');
strict.ok('code' in caughtErr!, 'code should be propagated');
strict.ok('sqlMessage' in caughtErr!, 'sqlMessage should be propagated');
});

await it('changeUser rejection should propagate error properties', async () => {
let caughtErr: MysqlError | undefined;
try {
await conn.changeUser({ user: 'nonexistent_user_xyz' });
} catch (err) {
caughtErr = err as MysqlError;
}
strict.ok(caughtErr, 'Expected changeUser to throw');
strict.ok('errno' in caughtErr!, 'errno should be propagated');
strict.ok('code' in caughtErr!, 'code should be propagated');
});

await conn.end();
});
Loading