Skip to content

Commit d78ba3b

Browse files
author
diego Dupin
committed
[CONJS-180] compatibility: support mysql2 stream option #173
1 parent 8d11d51 commit d78ba3b

File tree

10 files changed

+130
-6
lines changed

10 files changed

+130
-6
lines changed

CHANGELOG.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
# Change Log
22

3-
## [3.0.1-rc](https://github.com/mariadb-corporation/mariadb-connector-nodejs/tree/3.0.1-rc) (???)
4-
[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-nodejs/compare/3.0.0-beta...3.0.1-rc)
3+
## [3.0.0-rc](https://github.com/mariadb-corporation/mariadb-connector-nodejs/tree/3.0.0-rc) (19 Oct 2021)
4+
[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-nodejs/compare/3.0.0-beta...3.0.0-rc)
55

66
Notable change:
77
* [CONJS-168] stream backpressure not handled well
88
* [CONJS-172] performance improvement for multi-line result-set + update perf result with recent mysql/mysql2 drivers see [dedicated part](https://github.com/mariadb-corporation/mariadb-connector-nodejs/blob/maintenance/3.x/documentation/benchmarks.md) results.
99
* [CONJS-168] correct stream backpressure
1010
* [CONJS-176] Change Pool cluster default option removeNodeErrorCount value to Infinity
1111
* [CONJS-175] Missing leakDetectionTimeout option in Typescript description
12-
12+
* [CONJS-178] Update code to recent Ecma version
13+
* [CONJS-179] better pool option `resetAfterUse` default value
14+
* [CONJS-180] compatibility: support mysql2 `stream` option
15+
*
1316
* Corrections:
1417
* [CONJS-125] permit using batch with returning clause
1518
* [CONJS-170] Pool.query(undefined) never release connection

documentation/connection-options.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,44 @@ mariadb.createConnection({
392392
| **restrictedAuth** | if set, restrict authentication plugin to secure list. Default provided plugins are mysql_native_password, mysql_clear_password, client_ed25519, dialog, sha256_password and caching_sha2_password |*Array|String* | |
393393
| **supportBigNumbers** | (deprecated) DECIMAL/BIGINT data type will be returned as number if in safe integer range, as string if not.|*boolean* | false |
394394
| **bigNumberStrings** | (deprecated) if set with `supportBigNumbers` DECIMAL/BIGINT data type will be returned as string |*boolean* | false |
395+
| **stream** | permits to set a function with parameter to set stream (since 3.0)|*function*| |
396+
397+
### SSH tunnel
398+
399+
In some cases, server is only available through an SSH tunnel.
400+
(This is of course not a recommended solution for production)
401+
402+
403+
The option `stream` permit defined a tunnel. stream function has callback (optional parameters : error, stream).
404+
405+
Example using `tunnel-ssh`:
406+
407+
```
408+
const conn = await mariadb.createConnection({
409+
user: 'myUser',
410+
password: 'mYpwd',
411+
port: 27000,
412+
stream: (cb) => {
413+
const tunnel = require('tunnel-ssh');
414+
tunnel(
415+
{
416+
// remote connection ssh info
417+
username: 'root',
418+
host: '157.230.123.7',
419+
port: 22,
420+
privateKey: fs.readFileSync('./pop_key.ppk'),
421+
// database (here on ssh server)
422+
dstHost: '127.0.0.1',
423+
dstPort: 3306,
424+
// local interface
425+
localHost: '127.0.0.1',
426+
localPort: 27000
427+
},
428+
cb
429+
);
430+
}
431+
});
432+
```
395433

396434

397435
## F.A.Q.

lib/config/connection-options.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class ConnectionOptions {
2828
this.user = opts.user || process.env.USERNAME;
2929
this.password = opts.password;
3030
this.database = opts.database;
31+
this.stream = opts.stream;
3132
if (opts.charset && typeof opts.charset === 'string') {
3233
this.collation = Collations.fromCharset(opts.charset.toLowerCase());
3334
if (this.collation === undefined) {

lib/connection.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ const OkPacket = require('./cmd/class/ok-packet');
2727
const Execute = require('./cmd/execute');
2828
const ClosePrepare = require('./cmd/close-prepare');
2929
const BatchBulk = require('./cmd/batch-bulk');
30-
const Stream = require('./cmd/stream');
3130
const ChangeUser = require('./cmd/change-user');
3231
const { Status } = require('./const/connection_status');
3332

@@ -773,10 +772,43 @@ class Connection extends EventEmitter {
773772
streamInitSocket(authFailHandler) {
774773
if (this.opts.socketPath) {
775774
this.socket = Net.connect(this.opts.socketPath);
775+
} else if (this.opts.stream) {
776+
if (typeof this.opts.stream === 'function') {
777+
const tmpSocket = this.opts.stream(
778+
function (err, stream) {
779+
if (err) {
780+
authFailHandler(err);
781+
return;
782+
} else if (stream) {
783+
this.socket = stream;
784+
this.socketInit(authFailHandler);
785+
} else {
786+
this.socket = Net.connect(this.opts.port, this.opts.host);
787+
this.socketInit(authFailHandler);
788+
}
789+
}.bind(this)
790+
);
791+
if (tmpSocket) {
792+
this.socket = tmpSocket;
793+
this.socketInit(authFailHandler);
794+
}
795+
} else {
796+
const err = Errors.createError(
797+
'stream option is not a function. stream must be a function with (error, callback) parameter',
798+
Errors.ER_BAD_PARAMETER_VALUE,
799+
this.info
800+
);
801+
authFailHandler(err);
802+
}
803+
return;
776804
} else {
777805
this.socket = Net.connect(this.opts.port, this.opts.host);
778806
}
779807

808+
this.socketInit(authFailHandler);
809+
}
810+
811+
socketInit(authFailHandler) {
780812
if (this.opts.connectTimeout) {
781813
this.timeout = setTimeout(
782814
this.connectTimeoutReached.bind(this),

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@
5151
"denque": "^1.5.0",
5252
"iconv-lite": "^0.6.3",
5353
"moment-timezone": "^0.5.33",
54-
"please-upgrade-node": "^3.2.0",
55-
"promise-mysql": "^5.0.4"
54+
"please-upgrade-node": "^3.2.0"
5655
},
5756
"devDependencies": {
5857
"@typescript-eslint/eslint-plugin": "^5.0.0",

test/integration/test-connection.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const Collations = require('../../lib/const/collations.js');
66
const Conf = require('../conf');
77
const Connection = require('../../lib/connection');
88
const ConnOptions = require('../../lib/config/connection-options');
9+
const Net = require('net');
910

1011
describe('connection', () => {
1112
it('with no connection attributes', function (done) {
@@ -434,6 +435,29 @@ describe('connection', () => {
434435
});
435436
});
436437

438+
it('stream basic test', async function () {
439+
const conn = await base.createConnection({
440+
stream: (cb) => {
441+
cb(null, new Net.connect(Conf.baseConfig.port, Conf.baseConfig.host));
442+
}
443+
});
444+
conn.end();
445+
446+
const conn2 = await base.createConnection({
447+
stream: () => {
448+
return new Net.connect(Conf.baseConfig.port, Conf.baseConfig.host);
449+
}
450+
});
451+
conn2.end();
452+
453+
const conn3 = await base.createConnection({
454+
stream: (cb) => {
455+
cb();
456+
}
457+
});
458+
conn3.end();
459+
});
460+
437461
it('connection error', function (done) {
438462
base
439463
.createConnection({

test/integration/test-error.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,18 @@ describe('Error', () => {
4747
.catch(done);
4848
});
4949

50+
it('stream type error', async function () {
51+
try {
52+
await base.createConnection({ stream: 'wrong' });
53+
throw new Error('must have thrown error');
54+
} catch (err) {
55+
assert.isTrue(err.message.includes('stream option is not a function'));
56+
assert.equal(err.errno, 45043);
57+
assert.equal(err.sqlState, 'HY000');
58+
assert.equal(err.code, 'ER_BAD_PARAMETER_VALUE');
59+
}
60+
});
61+
5062
it('query callback error with trace', function (done) {
5163
const conn = base.createCallbackConnection({ trace: true });
5264
conn.connect((err1) => {

test/unit/config/test-options.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ describe('test options', () => {
6161
insertIdAsNumber: false,
6262
skipSetTimezone: false,
6363
typeCast: undefined,
64+
stream: undefined,
6465
bigIntAsNumber: false,
6566
bulk: true,
6667
permitLocalInfile: false,

types/index.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export interface LoggerConfig {
2525
error?: (err: Error) => void;
2626
}
2727

28+
export function StreamCallback(err?: Error, stream?: stream.Duplex): void;
29+
2830
export interface QueryConfig {
2931
/**
3032
* Presents result-sets by table to avoid results with colliding fields.
@@ -344,6 +346,14 @@ export interface ConnectionConfig extends UserConnectionConfig, QueryConfig {
344346
* default to 256.
345347
*/
346348
prepareCacheLength?: number;
349+
350+
/**
351+
* Permit to set stream.
352+
*
353+
* @param err error is any error occurs during stream creation
354+
* @param stream if wanting to set a special stream (Standard socket will be created if not set)
355+
*/
356+
stream?: (callback?: typeof StreamCallback) => void;
347357
}
348358

349359
export interface PoolConfig extends ConnectionConfig {

types/mariadb-tests.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ function createConnection(option?: ConnectionConfig): Promise<mariadb.Connection
1414
network: (msg) => console.log(msg),
1515
query: (msg) => console.log(msg),
1616
error: (err) => console.log(err)
17+
},
18+
stream: (callback) => {
19+
console.log('test');
20+
callback(null, null);
1721
}
1822
});
1923
}

0 commit comments

Comments
 (0)