mysql2 3.19.1 → 3.19.2-canary.7e57db62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/base/connection.js +166 -19
- package/lib/base/pool.js +71 -40
- package/lib/pool_connection.js +71 -2
- package/lib/promise/pool_connection.js +1 -5
- package/lib/tracing.js +81 -0
- package/package.json +11 -12
- package/promise.d.ts +2 -2
- package/promise.js +2 -0
- package/typings/mysql/index.d.ts +8 -3
- package/typings/mysql/lib/Tracing.d.ts +71 -0
- package/lib/base/pool_connection.js +0 -77
package/lib/base/connection.js
CHANGED
|
@@ -28,6 +28,15 @@ const Packets = require('../packets/index.js');
|
|
|
28
28
|
const Commands = require('../commands/index.js');
|
|
29
29
|
const ConnectionConfig = require('../connection_config.js');
|
|
30
30
|
const CharsetToEncoding = require('../constants/charset_encodings.js');
|
|
31
|
+
const {
|
|
32
|
+
traceCallback,
|
|
33
|
+
tracePromise,
|
|
34
|
+
getServerContext,
|
|
35
|
+
shouldTrace,
|
|
36
|
+
queryChannel,
|
|
37
|
+
executeChannel,
|
|
38
|
+
connectChannel,
|
|
39
|
+
} = require('../tracing.js');
|
|
31
40
|
|
|
32
41
|
let _connectionId = 0;
|
|
33
42
|
|
|
@@ -141,6 +150,41 @@ class BaseConnection extends EventEmitter {
|
|
|
141
150
|
this._notifyError(err);
|
|
142
151
|
});
|
|
143
152
|
this.addCommand(handshakeCommand);
|
|
153
|
+
|
|
154
|
+
// Trace the connection handshake
|
|
155
|
+
if (shouldTrace(connectChannel)) {
|
|
156
|
+
const config = this.config;
|
|
157
|
+
tracePromise(
|
|
158
|
+
connectChannel,
|
|
159
|
+
() =>
|
|
160
|
+
new Promise((resolve, reject) => {
|
|
161
|
+
/* eslint-disable prefer-const */
|
|
162
|
+
let onConnect, onError;
|
|
163
|
+
onConnect = (param) => {
|
|
164
|
+
this.removeListener('error', onError);
|
|
165
|
+
resolve(param);
|
|
166
|
+
};
|
|
167
|
+
onError = (err) => {
|
|
168
|
+
this.removeListener('connect', onConnect);
|
|
169
|
+
reject(err);
|
|
170
|
+
};
|
|
171
|
+
/* eslint-enable prefer-const */
|
|
172
|
+
this.once('connect', onConnect);
|
|
173
|
+
this.once('error', onError);
|
|
174
|
+
}),
|
|
175
|
+
() => {
|
|
176
|
+
const server = getServerContext(config);
|
|
177
|
+
return {
|
|
178
|
+
database: config.database || '',
|
|
179
|
+
serverAddress: server.serverAddress,
|
|
180
|
+
serverPort: server.serverPort,
|
|
181
|
+
user: config.user || '',
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
).catch(() => {
|
|
185
|
+
// errors are already handled by the handshake error listener
|
|
186
|
+
});
|
|
187
|
+
}
|
|
144
188
|
}
|
|
145
189
|
// in case there was no initial handshake but we need to read sting, assume it utf-8
|
|
146
190
|
// most common example: "Too many connections" error ( packet is sent immediately on connection attempt, we don't know server encoding yet)
|
|
@@ -601,7 +645,57 @@ class BaseConnection extends EventEmitter {
|
|
|
601
645
|
cmdQuery.values !== undefined ? cmdQuery.values : []
|
|
602
646
|
);
|
|
603
647
|
cmdQuery.sql = rawSql;
|
|
604
|
-
|
|
648
|
+
|
|
649
|
+
if (cmdQuery.onResult) {
|
|
650
|
+
// Callback mode: traceCallback wraps the callback with tracing lifecycle, or calls through directly when no subscribers are registered
|
|
651
|
+
traceCallback(
|
|
652
|
+
queryChannel,
|
|
653
|
+
(wrappedCb) => {
|
|
654
|
+
cmdQuery.onResult = wrappedCb;
|
|
655
|
+
this.addCommand(cmdQuery);
|
|
656
|
+
},
|
|
657
|
+
0,
|
|
658
|
+
() => {
|
|
659
|
+
const server = getServerContext(this.config);
|
|
660
|
+
return {
|
|
661
|
+
query: cmdQuery.sql,
|
|
662
|
+
values: cmdQuery.values,
|
|
663
|
+
database: this.config.database || '',
|
|
664
|
+
serverAddress: server.serverAddress,
|
|
665
|
+
serverPort: server.serverPort,
|
|
666
|
+
};
|
|
667
|
+
},
|
|
668
|
+
null,
|
|
669
|
+
cmdQuery.onResult
|
|
670
|
+
);
|
|
671
|
+
} else if (shouldTrace(queryChannel)) {
|
|
672
|
+
// Event-emitter mode: tracePromise wraps the async lifecycle
|
|
673
|
+
tracePromise(
|
|
674
|
+
queryChannel,
|
|
675
|
+
() =>
|
|
676
|
+
new Promise((resolve, reject) => {
|
|
677
|
+
cmdQuery.once('error', reject);
|
|
678
|
+
cmdQuery.once('end', () => resolve());
|
|
679
|
+
this.addCommand(cmdQuery);
|
|
680
|
+
}),
|
|
681
|
+
() => {
|
|
682
|
+
const server = getServerContext(this.config);
|
|
683
|
+
return {
|
|
684
|
+
query: cmdQuery.sql,
|
|
685
|
+
values: cmdQuery.values,
|
|
686
|
+
database: this.config.database || '',
|
|
687
|
+
serverAddress: server.serverAddress,
|
|
688
|
+
serverPort: server.serverPort,
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
).catch(() => {
|
|
692
|
+
// errors are already emitted on the command
|
|
693
|
+
});
|
|
694
|
+
} else {
|
|
695
|
+
this.addCommand(cmdQuery);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
return cmdQuery;
|
|
605
699
|
}
|
|
606
700
|
|
|
607
701
|
pause() {
|
|
@@ -702,25 +796,78 @@ class BaseConnection extends EventEmitter {
|
|
|
702
796
|
});
|
|
703
797
|
}
|
|
704
798
|
const executeCommand = new Commands.Execute(options, cb);
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
799
|
+
|
|
800
|
+
const prepareAndExecute = (errorCb) => {
|
|
801
|
+
const prepareCommand = new Commands.Prepare(options, (err, stmt) => {
|
|
802
|
+
if (err) {
|
|
803
|
+
// skip execute command if prepare failed
|
|
804
|
+
executeCommand.start = function () {
|
|
805
|
+
return null;
|
|
806
|
+
};
|
|
807
|
+
errorCb(err);
|
|
808
|
+
executeCommand.emit('end');
|
|
809
|
+
return;
|
|
716
810
|
}
|
|
717
|
-
executeCommand.
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
executeCommand
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
|
|
811
|
+
executeCommand.statement = stmt;
|
|
812
|
+
});
|
|
813
|
+
this.addCommand(prepareCommand);
|
|
814
|
+
this.addCommand(executeCommand);
|
|
815
|
+
};
|
|
816
|
+
|
|
817
|
+
if (executeCommand.onResult) {
|
|
818
|
+
// Callback mode: traceCallback wraps the callback with tracing lifecycle, or calls through directly when no subscribers are registered
|
|
819
|
+
const origExecCb = executeCommand.onResult;
|
|
820
|
+
traceCallback(
|
|
821
|
+
executeChannel,
|
|
822
|
+
(wrappedCb) => {
|
|
823
|
+
executeCommand.onResult = wrappedCb;
|
|
824
|
+
prepareAndExecute(wrappedCb);
|
|
825
|
+
},
|
|
826
|
+
0,
|
|
827
|
+
() => {
|
|
828
|
+
const server = getServerContext(this.config);
|
|
829
|
+
return {
|
|
830
|
+
query: options.sql,
|
|
831
|
+
values: options.values,
|
|
832
|
+
database: this.config.database || '',
|
|
833
|
+
serverAddress: server.serverAddress,
|
|
834
|
+
serverPort: server.serverPort,
|
|
835
|
+
};
|
|
836
|
+
},
|
|
837
|
+
null,
|
|
838
|
+
origExecCb
|
|
839
|
+
);
|
|
840
|
+
} else if (shouldTrace(executeChannel)) {
|
|
841
|
+
// Event-emitter mode: tracePromise wraps the async lifecycle
|
|
842
|
+
tracePromise(
|
|
843
|
+
executeChannel,
|
|
844
|
+
() =>
|
|
845
|
+
new Promise((resolve, reject) => {
|
|
846
|
+
prepareAndExecute((err) => {
|
|
847
|
+
executeCommand.emit('error', err);
|
|
848
|
+
});
|
|
849
|
+
executeCommand.once('error', reject);
|
|
850
|
+
executeCommand.once('end', () => resolve());
|
|
851
|
+
}),
|
|
852
|
+
() => {
|
|
853
|
+
const server = getServerContext(this.config);
|
|
854
|
+
return {
|
|
855
|
+
query: options.sql,
|
|
856
|
+
values: options.values,
|
|
857
|
+
database: this.config.database || '',
|
|
858
|
+
serverAddress: server.serverAddress,
|
|
859
|
+
serverPort: server.serverPort,
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
).catch(() => {
|
|
863
|
+
// errors are already emitted on the command
|
|
864
|
+
});
|
|
865
|
+
} else {
|
|
866
|
+
prepareAndExecute((err) => {
|
|
867
|
+
executeCommand.emit('error', err);
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
|
|
724
871
|
return executeCommand;
|
|
725
872
|
}
|
|
726
873
|
|
package/lib/base/pool.js
CHANGED
|
@@ -7,6 +7,11 @@ const PoolConnection = require('../pool_connection.js');
|
|
|
7
7
|
const Queue = require('denque');
|
|
8
8
|
const BaseConnection = require('./connection.js');
|
|
9
9
|
const Errors = require('../constants/errors.js');
|
|
10
|
+
const {
|
|
11
|
+
traceCallback,
|
|
12
|
+
getServerContext,
|
|
13
|
+
poolConnectChannel,
|
|
14
|
+
} = require('../tracing.js');
|
|
10
15
|
|
|
11
16
|
// Source: https://github.com/go-sql-driver/mysql/blob/76c00e35a8d48f8f70f0e7dffe584692bd3fa612/packets.go#L598-L613
|
|
12
17
|
function isReadOnlyError(err) {
|
|
@@ -49,46 +54,69 @@ class BasePool extends EventEmitter {
|
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
getConnection(cb) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return process.nextTick(() => cb(null, connection));
|
|
60
|
-
}
|
|
61
|
-
if (
|
|
62
|
-
this.config.connectionLimit === 0 ||
|
|
63
|
-
this._allConnections.length < this.config.connectionLimit
|
|
64
|
-
) {
|
|
65
|
-
connection = new PoolConnection(this, {
|
|
66
|
-
config: this.config.connectionConfig,
|
|
67
|
-
});
|
|
68
|
-
this._allConnections.push(connection);
|
|
69
|
-
return connection.connect((err) => {
|
|
70
|
-
if (this._closed) {
|
|
71
|
-
return cb(new Error('Pool is closed.'));
|
|
72
|
-
}
|
|
73
|
-
if (err) {
|
|
74
|
-
return cb(err);
|
|
75
|
-
}
|
|
76
|
-
this.emit('connection', connection);
|
|
57
|
+
const _getConnection = (cb) => {
|
|
58
|
+
if (this._closed) {
|
|
59
|
+
return process.nextTick(() => cb(new Error('Pool is closed.')));
|
|
60
|
+
}
|
|
61
|
+
let connection;
|
|
62
|
+
if (this._freeConnections.length > 0) {
|
|
63
|
+
connection = this._freeConnections.pop();
|
|
77
64
|
this.emit('acquire', connection);
|
|
78
|
-
return
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
65
|
+
return process.nextTick(() => {
|
|
66
|
+
connection._released = false;
|
|
67
|
+
cb(null, connection);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (
|
|
71
|
+
this.config.connectionLimit === 0 ||
|
|
72
|
+
this._allConnections.length < this.config.connectionLimit
|
|
73
|
+
) {
|
|
74
|
+
connection = new PoolConnection(this, {
|
|
75
|
+
config: this.config.connectionConfig,
|
|
76
|
+
});
|
|
77
|
+
this._allConnections.push(connection);
|
|
78
|
+
return connection.connect((err) => {
|
|
79
|
+
if (this._closed) {
|
|
80
|
+
return cb(new Error('Pool is closed.'));
|
|
81
|
+
}
|
|
82
|
+
if (err) {
|
|
83
|
+
return cb(err);
|
|
84
|
+
}
|
|
85
|
+
this.emit('connection', connection);
|
|
86
|
+
this.emit('acquire', connection);
|
|
87
|
+
return cb(null, connection);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (!this.config.waitForConnections) {
|
|
91
|
+
return process.nextTick(() =>
|
|
92
|
+
cb(new Error('No connections available.'))
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
if (
|
|
96
|
+
this.config.queueLimit &&
|
|
97
|
+
this._connectionQueue.length >= this.config.queueLimit
|
|
98
|
+
) {
|
|
99
|
+
return cb(new Error('Queue limit reached.'));
|
|
100
|
+
}
|
|
101
|
+
this.emit('enqueue');
|
|
102
|
+
return this._connectionQueue.push(cb);
|
|
103
|
+
};
|
|
104
|
+
const config = this.config.connectionConfig;
|
|
105
|
+
traceCallback(
|
|
106
|
+
poolConnectChannel,
|
|
107
|
+
_getConnection,
|
|
108
|
+
0,
|
|
109
|
+
() => {
|
|
110
|
+
const server = getServerContext(config);
|
|
111
|
+
return {
|
|
112
|
+
database: config.database || '',
|
|
113
|
+
serverAddress: server.serverAddress,
|
|
114
|
+
serverPort: server.serverPort,
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
null,
|
|
118
|
+
cb
|
|
119
|
+
);
|
|
92
120
|
}
|
|
93
121
|
|
|
94
122
|
releaseConnection(connection) {
|
|
@@ -101,7 +129,10 @@ class BasePool extends EventEmitter {
|
|
|
101
129
|
}
|
|
102
130
|
} else if (this._connectionQueue.length) {
|
|
103
131
|
cb = this._connectionQueue.shift();
|
|
104
|
-
process.nextTick(
|
|
132
|
+
process.nextTick(() => {
|
|
133
|
+
connection._released = false;
|
|
134
|
+
cb(null, connection);
|
|
135
|
+
});
|
|
105
136
|
} else {
|
|
106
137
|
this._freeConnections.push(connection);
|
|
107
138
|
this.emit('release', connection);
|
package/lib/pool_connection.js
CHANGED
|
@@ -1,12 +1,81 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Connection = require('./connection.js');
|
|
4
|
+
|
|
5
|
+
class PoolConnection extends Connection {
|
|
6
|
+
constructor(pool, options) {
|
|
7
|
+
super(options);
|
|
8
|
+
this._pool = pool;
|
|
9
|
+
this._released = false;
|
|
10
|
+
this.lastActiveTime = Date.now();
|
|
11
|
+
this.once('end', () => {
|
|
12
|
+
this._removeFromPool();
|
|
13
|
+
});
|
|
14
|
+
this.once('error', () => {
|
|
15
|
+
this._removeFromPool();
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
release() {
|
|
20
|
+
if (this._released) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (!this._pool || this._pool._closed) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this._released = true;
|
|
27
|
+
this.lastActiveTime = Date.now();
|
|
28
|
+
this._pool.releaseConnection(this);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
[Symbol.dispose]() {
|
|
32
|
+
this.release();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
end(callback) {
|
|
36
|
+
if (this.config.gracefulEnd) {
|
|
37
|
+
this._removeFromPool();
|
|
38
|
+
super.end(callback);
|
|
39
|
+
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const err = new Error(
|
|
44
|
+
'Calling conn.end() to release a pooled connection is ' +
|
|
45
|
+
'deprecated. In next version calling conn.end() will be ' +
|
|
46
|
+
'restored to default conn.end() behavior. Use ' +
|
|
47
|
+
'conn.release() instead.'
|
|
48
|
+
);
|
|
49
|
+
this.emit('warn', err);
|
|
50
|
+
console.warn(err.message);
|
|
51
|
+
this.release();
|
|
52
|
+
if (typeof callback === 'function') {
|
|
53
|
+
callback();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
destroy() {
|
|
58
|
+
this._removeFromPool();
|
|
59
|
+
super.destroy();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
_removeFromPool() {
|
|
63
|
+
if (!this._pool || this._pool._closed) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const pool = this._pool;
|
|
67
|
+
this._pool = null;
|
|
68
|
+
pool._removeConnection(this);
|
|
69
|
+
}
|
|
4
70
|
|
|
5
|
-
class PoolConnection extends BasePoolConnection {
|
|
6
71
|
promise(promiseImpl) {
|
|
7
72
|
const PromisePoolConnection = require('./promise/pool_connection.js');
|
|
8
73
|
return new PromisePoolConnection(this, promiseImpl);
|
|
9
74
|
}
|
|
10
75
|
}
|
|
11
76
|
|
|
77
|
+
PoolConnection.statementKey = Connection.statementKey;
|
|
12
78
|
module.exports = PoolConnection;
|
|
79
|
+
|
|
80
|
+
// TODO: Remove this when we are removing PoolConnection#end
|
|
81
|
+
PoolConnection.prototype._realEnd = Connection.prototype.end;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const PromiseConnection = require('./connection.js');
|
|
4
|
-
const BasePoolConnection = require('../base/pool_connection.js');
|
|
5
4
|
|
|
6
5
|
class PromisePoolConnection extends PromiseConnection {
|
|
7
6
|
constructor(connection, promiseImpl) {
|
|
@@ -9,10 +8,7 @@ class PromisePoolConnection extends PromiseConnection {
|
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
destroy() {
|
|
12
|
-
return
|
|
13
|
-
this.connection,
|
|
14
|
-
arguments
|
|
15
|
-
);
|
|
11
|
+
return this.connection.destroy();
|
|
16
12
|
}
|
|
17
13
|
|
|
18
14
|
async [Symbol.asyncDispose]() {
|
package/lib/tracing.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const process = require('process');
|
|
4
|
+
|
|
5
|
+
// Safe load: use getBuiltinModule if available, fallback to require, catch if unavailable
|
|
6
|
+
const dc = (() => {
|
|
7
|
+
try {
|
|
8
|
+
return 'getBuiltinModule' in process
|
|
9
|
+
? process.getBuiltinModule('node:diagnostics_channel')
|
|
10
|
+
: require('node:diagnostics_channel');
|
|
11
|
+
} catch {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
})();
|
|
15
|
+
|
|
16
|
+
const hasTracingChannel = typeof dc?.tracingChannel === 'function';
|
|
17
|
+
|
|
18
|
+
const queryChannel = hasTracingChannel
|
|
19
|
+
? dc.tracingChannel('mysql2:query')
|
|
20
|
+
: undefined;
|
|
21
|
+
|
|
22
|
+
const executeChannel = hasTracingChannel
|
|
23
|
+
? dc.tracingChannel('mysql2:execute')
|
|
24
|
+
: undefined;
|
|
25
|
+
|
|
26
|
+
const connectChannel = hasTracingChannel
|
|
27
|
+
? dc.tracingChannel('mysql2:connect')
|
|
28
|
+
: undefined;
|
|
29
|
+
|
|
30
|
+
const poolConnectChannel = hasTracingChannel
|
|
31
|
+
? dc.tracingChannel('mysql2:pool:connect')
|
|
32
|
+
: undefined;
|
|
33
|
+
|
|
34
|
+
function getServerContext(config) {
|
|
35
|
+
if (config.socketPath) {
|
|
36
|
+
return { serverAddress: config.socketPath, serverPort: undefined };
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
serverAddress: config.host || 'localhost',
|
|
40
|
+
serverPort: config.port || 3306,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Node 20+: TracingChannel has an aggregated hasSubscribers getter.
|
|
45
|
+
// Node 18.x: that getter is missing (undefined), fall back to start sub-channel.
|
|
46
|
+
function shouldTrace(channel) {
|
|
47
|
+
if (channel === undefined || channel === null) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return channel.hasSubscribers ?? channel.start?.hasSubscribers ?? false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Generic traceCallback wrapper — calls fn synchronously, wraps the callback
|
|
54
|
+
// at args[position] to emit asyncStart/asyncEnd/error. No promises involved.
|
|
55
|
+
function traceCallback(channel, fn, position, context, thisArg, ...args) {
|
|
56
|
+
if (shouldTrace(channel)) {
|
|
57
|
+
return channel.traceCallback(fn, position, context(), thisArg, ...args);
|
|
58
|
+
}
|
|
59
|
+
return fn.apply(thisArg, args);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// tracePromise for operations that are inherently async (connection handshake)
|
|
63
|
+
function tracePromise(channel, fn, contextFactory) {
|
|
64
|
+
if (shouldTrace(channel)) {
|
|
65
|
+
return channel.tracePromise(fn, contextFactory());
|
|
66
|
+
}
|
|
67
|
+
return fn();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
dc,
|
|
72
|
+
hasTracingChannel,
|
|
73
|
+
shouldTrace,
|
|
74
|
+
queryChannel,
|
|
75
|
+
executeChannel,
|
|
76
|
+
connectChannel,
|
|
77
|
+
poolConnectChannel,
|
|
78
|
+
getServerContext,
|
|
79
|
+
traceCallback,
|
|
80
|
+
tracePromise,
|
|
81
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mysql2",
|
|
3
|
-
"version": "3.19.
|
|
3
|
+
"version": "3.19.2-canary.7e57db62",
|
|
4
4
|
"description": "fast mysql driver. Implements core protocol, prepared statements, ssl and compression in native JS",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "typings/mysql/index",
|
|
@@ -8,15 +8,9 @@
|
|
|
8
8
|
"scripts": {
|
|
9
9
|
"lint": "eslint . && prettier --check .",
|
|
10
10
|
"lint:fix": "eslint . --fix && prettier --write .",
|
|
11
|
-
"test": "
|
|
12
|
-
"test:
|
|
13
|
-
"test:
|
|
14
|
-
"test:bun": "npm run test:bun:parallel && npm run test:bun:global",
|
|
15
|
-
"test:bun:parallel": "bun poku -c=\"poku.config.mjs\" test",
|
|
16
|
-
"test:bun:global": "cross-env SUITE=global bun poku -c=\"poku.config.mjs\" test/global",
|
|
17
|
-
"test:deno": "npm run test:deno:parallel && npm run test:deno:global",
|
|
18
|
-
"test:deno:parallel": "deno run --allow-read --allow-env --allow-run npm:poku -c=\"poku.config.mjs\" test",
|
|
19
|
-
"test:deno:global": "cross-env SUITE=global deno run --allow-read --allow-env --allow-run npm:poku -c=\"poku.config.mjs\" test/global",
|
|
11
|
+
"test": "poku",
|
|
12
|
+
"test:bun": "bun poku",
|
|
13
|
+
"test:deno": "deno run -A npm:poku",
|
|
20
14
|
"test:docker:up": "docker compose -f test/docker-compose.yml up --abort-on-container-exit --remove-orphans",
|
|
21
15
|
"test:docker:down": "docker compose -f test/docker-compose.yml down",
|
|
22
16
|
"test:docker:node": "npm run test:docker:up -- node && npm run test:docker:down",
|
|
@@ -24,6 +18,7 @@
|
|
|
24
18
|
"test:docker:deno": "npm run test:docker:up -- deno && npm run test:docker:down",
|
|
25
19
|
"test:docker:coverage": "npm run test:docker:up -- coverage && npm run test:docker:down",
|
|
26
20
|
"test:coverage": "c8 npm test",
|
|
21
|
+
"test:build": "rollup -c",
|
|
27
22
|
"typecheck": "cd \"test/tsc-build\" && tsc -p \"tsconfig.json\" && cd .. && tsc -p \"tsconfig.json\" --noEmit",
|
|
28
23
|
"benchmark": "node ./benchmarks/benchmark.js",
|
|
29
24
|
"wait-port": "wait-on"
|
|
@@ -75,21 +70,25 @@
|
|
|
75
70
|
"@eslint/js": "^9.39.2",
|
|
76
71
|
"@eslint/markdown": "^7.5.1",
|
|
77
72
|
"@ianvs/prettier-plugin-sort-imports": "^4.7.1",
|
|
73
|
+
"@pokujs/multi-suite": "^1.0.0",
|
|
74
|
+
"@rollup/plugin-commonjs": "^29.0.2",
|
|
75
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
76
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
78
77
|
"@types/node": "^25.3.0",
|
|
79
78
|
"@typescript-eslint/eslint-plugin": "^8.56.0",
|
|
80
79
|
"@typescript-eslint/parser": "^8.56.0",
|
|
81
80
|
"assert-diff": "^3.0.4",
|
|
82
81
|
"benchmark": "^2.1.4",
|
|
83
82
|
"c8": "^11.0.0",
|
|
84
|
-
"cross-env": "^10.1.0",
|
|
85
83
|
"error-stack-parser": "^2.1.4",
|
|
86
84
|
"eslint-config-prettier": "^10.1.8",
|
|
87
85
|
"eslint-plugin-async-await": "^0.0.0",
|
|
88
86
|
"eslint-plugin-prettier": "^5.5.5",
|
|
89
87
|
"globals": "^17.3.0",
|
|
90
|
-
"poku": "^4.
|
|
88
|
+
"poku": "^4.1.0",
|
|
91
89
|
"portfinder": "^1.0.38",
|
|
92
90
|
"prettier": "^3.8.1",
|
|
91
|
+
"rollup": "^4.59.0",
|
|
93
92
|
"tsx": "^4.21.0",
|
|
94
93
|
"typescript": "^5.9.3"
|
|
95
94
|
}
|
package/promise.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface PreparedStatementInfo {
|
|
|
40
40
|
>;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export
|
|
43
|
+
export declare class Connection extends QueryableAndExecutableBase {
|
|
44
44
|
config: ConnectionOptions;
|
|
45
45
|
|
|
46
46
|
threadId: number;
|
|
@@ -81,7 +81,7 @@ export interface Connection extends QueryableAndExecutableBase {
|
|
|
81
81
|
format(sql: string, values?: any | any[] | { [param: string]: any }): string;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
export
|
|
84
|
+
export declare class PoolConnection extends Connection {
|
|
85
85
|
release(): void;
|
|
86
86
|
connection: Connection;
|
|
87
87
|
[Symbol.asyncDispose](): Promise<void>;
|
package/promise.js
CHANGED
|
@@ -185,6 +185,8 @@ exports.escape = SqlString.escape;
|
|
|
185
185
|
exports.escapeId = SqlString.escapeId;
|
|
186
186
|
exports.format = SqlString.format;
|
|
187
187
|
exports.raw = SqlString.raw;
|
|
188
|
+
exports.Connection = PromiseConnection;
|
|
189
|
+
exports.PoolConnection = PromisePoolConnection;
|
|
188
190
|
exports.PromisePool = PromisePool;
|
|
189
191
|
exports.PromiseConnection = PromiseConnection;
|
|
190
192
|
exports.PromisePoolConnection = PromisePoolConnection;
|
package/typings/mysql/index.d.ts
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
PoolClusterOptions,
|
|
15
15
|
PoolNamespace,
|
|
16
16
|
} from './lib/PoolCluster.js';
|
|
17
|
-
import { PoolConnection as BasePoolConnection } from './lib/PoolConnection.js';
|
|
18
17
|
import {
|
|
19
18
|
Prepare as BasePrepare,
|
|
20
19
|
PrepareStatementInfo,
|
|
@@ -44,11 +43,10 @@ export * from './lib/Auth.js';
|
|
|
44
43
|
export * from './lib/constants/index.js';
|
|
45
44
|
export * from './lib/parsers/index.js';
|
|
46
45
|
export * from './lib/Connection.js';
|
|
46
|
+
export * from './lib/PoolConnection.js';
|
|
47
47
|
|
|
48
48
|
// Expose class interfaces
|
|
49
|
-
export interface Connection extends BaseConnection {}
|
|
50
49
|
export interface Pool extends BasePool {}
|
|
51
|
-
export interface PoolConnection extends BasePoolConnection {}
|
|
52
50
|
export interface PoolCluster extends BasePoolCluster {}
|
|
53
51
|
export interface Query extends BaseQuery {}
|
|
54
52
|
export interface Prepare extends BasePrepare {}
|
|
@@ -82,3 +80,10 @@ export interface ConnectionConfig extends ConnectionOptions {
|
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
export function createServer(handler: (conn: BaseConnection) => any): Server;
|
|
83
|
+
|
|
84
|
+
export type {
|
|
85
|
+
QueryTraceContext,
|
|
86
|
+
ExecuteTraceContext,
|
|
87
|
+
ConnectTraceContext,
|
|
88
|
+
PoolConnectTraceContext,
|
|
89
|
+
} from './lib/Tracing.js';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { TracingChannel } from 'node:diagnostics_channel';
|
|
2
|
+
|
|
3
|
+
export interface QueryTraceContext {
|
|
4
|
+
query: string;
|
|
5
|
+
values: any;
|
|
6
|
+
database: string;
|
|
7
|
+
serverAddress: string;
|
|
8
|
+
serverPort: number | undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ExecuteTraceContext {
|
|
12
|
+
query: string;
|
|
13
|
+
values: any;
|
|
14
|
+
database: string;
|
|
15
|
+
serverAddress: string;
|
|
16
|
+
serverPort: number | undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ConnectTraceContext {
|
|
20
|
+
database: string;
|
|
21
|
+
serverAddress: string;
|
|
22
|
+
serverPort: number | undefined;
|
|
23
|
+
user: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface PoolConnectTraceContext {
|
|
27
|
+
database: string;
|
|
28
|
+
serverAddress: string;
|
|
29
|
+
serverPort: number | undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export declare const dc: typeof import('node:diagnostics_channel') | undefined;
|
|
33
|
+
export declare const hasTracingChannel: boolean;
|
|
34
|
+
|
|
35
|
+
export declare function shouldTrace(
|
|
36
|
+
channel: TracingChannel<object> | undefined | null
|
|
37
|
+
): boolean;
|
|
38
|
+
|
|
39
|
+
export declare function traceCallback<T extends object>(
|
|
40
|
+
channel: TracingChannel<T> | undefined | null,
|
|
41
|
+
fn: (...args: any[]) => any,
|
|
42
|
+
position: number,
|
|
43
|
+
contextFactory: () => T,
|
|
44
|
+
thisArg: any,
|
|
45
|
+
...args: any[]
|
|
46
|
+
): any;
|
|
47
|
+
|
|
48
|
+
export declare function tracePromise<T extends object, R>(
|
|
49
|
+
channel: TracingChannel<T> | undefined | null,
|
|
50
|
+
fn: () => Promise<R>,
|
|
51
|
+
contextFactory: () => T
|
|
52
|
+
): Promise<R>;
|
|
53
|
+
|
|
54
|
+
export declare const queryChannel:
|
|
55
|
+
| TracingChannel<QueryTraceContext>
|
|
56
|
+
| undefined;
|
|
57
|
+
export declare const executeChannel:
|
|
58
|
+
| TracingChannel<ExecuteTraceContext>
|
|
59
|
+
| undefined;
|
|
60
|
+
export declare const connectChannel:
|
|
61
|
+
| TracingChannel<ConnectTraceContext>
|
|
62
|
+
| undefined;
|
|
63
|
+
export declare const poolConnectChannel:
|
|
64
|
+
| TracingChannel<PoolConnectTraceContext>
|
|
65
|
+
| undefined;
|
|
66
|
+
|
|
67
|
+
export declare function getServerContext(config: {
|
|
68
|
+
socketPath?: string;
|
|
69
|
+
host?: string;
|
|
70
|
+
port?: number;
|
|
71
|
+
}): { serverAddress: string; serverPort: number | undefined };
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const BaseConnection = require('./connection.js');
|
|
4
|
-
|
|
5
|
-
class BasePoolConnection extends BaseConnection {
|
|
6
|
-
constructor(pool, options) {
|
|
7
|
-
super(options);
|
|
8
|
-
this._pool = pool;
|
|
9
|
-
// The last active time of this connection
|
|
10
|
-
this.lastActiveTime = Date.now();
|
|
11
|
-
// When a fatal error occurs the connection's protocol ends, which will cause
|
|
12
|
-
// the connection to end as well, thus we only need to watch for the end event
|
|
13
|
-
// and we will be notified of disconnects.
|
|
14
|
-
// REVIEW: Moved to `once`
|
|
15
|
-
this.once('end', () => {
|
|
16
|
-
this._removeFromPool();
|
|
17
|
-
});
|
|
18
|
-
this.once('error', () => {
|
|
19
|
-
this._removeFromPool();
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
release() {
|
|
24
|
-
if (!this._pool || this._pool._closed) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
// update last active time
|
|
28
|
-
this.lastActiveTime = Date.now();
|
|
29
|
-
this._pool.releaseConnection(this);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
[Symbol.dispose]() {
|
|
33
|
-
this.release();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
end(callback) {
|
|
37
|
-
if (this.config.gracefulEnd) {
|
|
38
|
-
this._removeFromPool();
|
|
39
|
-
super.end(callback);
|
|
40
|
-
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const err = new Error(
|
|
45
|
-
'Calling conn.end() to release a pooled connection is ' +
|
|
46
|
-
'deprecated. In next version calling conn.end() will be ' +
|
|
47
|
-
'restored to default conn.end() behavior. Use ' +
|
|
48
|
-
'conn.release() instead.'
|
|
49
|
-
);
|
|
50
|
-
this.emit('warn', err);
|
|
51
|
-
console.warn(err.message);
|
|
52
|
-
this.release();
|
|
53
|
-
if (typeof callback === 'function') {
|
|
54
|
-
callback();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
destroy() {
|
|
59
|
-
this._removeFromPool();
|
|
60
|
-
super.destroy();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
_removeFromPool() {
|
|
64
|
-
if (!this._pool || this._pool._closed) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const pool = this._pool;
|
|
68
|
-
this._pool = null;
|
|
69
|
-
pool._removeConnection(this);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
BasePoolConnection.statementKey = BaseConnection.statementKey;
|
|
74
|
-
module.exports = BasePoolConnection;
|
|
75
|
-
|
|
76
|
-
// TODO: Remove this when we are removing PoolConnection#end
|
|
77
|
-
BasePoolConnection.prototype._realEnd = BaseConnection.prototype.end;
|