mysql2 3.21.2-canary.884bec56 → 3.22.0

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.
@@ -928,6 +928,10 @@ class BaseConnection extends EventEmitter {
928
928
  return this.addCommand(new Commands.Ping(cb));
929
929
  }
930
930
 
931
+ reset(cb) {
932
+ return this.addCommand(new Commands.ResetConnection(cb));
933
+ }
934
+
931
935
  _registerSlave(opts, cb) {
932
936
  return this.addCommand(new Commands.RegisterSlave(opts, cb));
933
937
  }
package/lib/base/pool.js CHANGED
@@ -127,7 +127,37 @@ class BasePool extends EventEmitter {
127
127
  cb = this._connectionQueue.shift();
128
128
  process.nextTick(this.getConnection.bind(this, cb));
129
129
  }
130
- } else if (this._connectionQueue.length) {
130
+ return;
131
+ }
132
+
133
+ // Reset connection state if configured
134
+ if (this.config.resetOnRelease && connection.reset) {
135
+ connection.reset((err) => {
136
+ if (err) {
137
+ // If reset fails, remove connection from pool
138
+ connection._pool = null;
139
+ spliceConnection(this._allConnections, connection);
140
+ connection.destroy();
141
+
142
+ // Try to create a new connection for waiting callbacks
143
+ if (this._connectionQueue.length) {
144
+ cb = this._connectionQueue.shift();
145
+ process.nextTick(this.getConnection.bind(this, cb));
146
+ }
147
+ return;
148
+ }
149
+
150
+ // Reset successful, continue with normal release flow
151
+ this._handleSuccessfulRelease(connection);
152
+ });
153
+ } else {
154
+ this._handleSuccessfulRelease(connection);
155
+ }
156
+ }
157
+
158
+ _handleSuccessfulRelease(connection) {
159
+ let cb;
160
+ if (this._connectionQueue.length) {
131
161
  cb = this._connectionQueue.shift();
132
162
  process.nextTick(() => {
133
163
  connection._released = false;
@@ -10,6 +10,7 @@ const Ping = require('./ping.js');
10
10
  const RegisterSlave = require('./register_slave.js');
11
11
  const BinlogDump = require('./binlog_dump.js');
12
12
  const ChangeUser = require('./change_user.js');
13
+ const ResetConnection = require('./reset_connection.js');
13
14
  const Quit = require('./quit.js');
14
15
 
15
16
  module.exports = {
@@ -23,5 +24,6 @@ module.exports = {
23
24
  RegisterSlave,
24
25
  BinlogDump,
25
26
  ChangeUser,
27
+ ResetConnection,
26
28
  Quit,
27
29
  };
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const Command = require('./command');
4
+ const Packets = require('../packets/index.js');
5
+
6
+ class ResetConnection extends Command {
7
+ constructor(callback) {
8
+ super();
9
+ this.onResult = callback;
10
+ }
11
+
12
+ start(packet, connection) {
13
+ const req = new Packets.ResetConnection();
14
+ connection.writePacket(req.toPacket());
15
+ return ResetConnection.prototype.resetConnectionResponse;
16
+ }
17
+
18
+ resetConnectionResponse(packet, connection) {
19
+ if (connection._statements) {
20
+ connection._statements.clear();
21
+ }
22
+ if (this.onResult) {
23
+ process.nextTick(this.onResult.bind(this, null));
24
+ }
25
+ return null;
26
+ }
27
+ }
28
+
29
+ module.exports = ResetConnection;
@@ -32,5 +32,6 @@ module.exports = {
32
32
  STMT_FETCH: 0x1c,
33
33
  DAEMON: 0x1d, // deprecated
34
34
  BINLOG_DUMP_GTID: 0x1e,
35
+ RESET_CONNECTION: 0x1f, // introduced in 5.7.3
35
36
  UNKNOWN: 0xff, // bad!
36
37
  };
@@ -27,6 +27,7 @@ const PrepareStatement = require('./prepare_statement');
27
27
  const PreparedStatementHeader = require('./prepared_statement_header');
28
28
  const Query = require('./query');
29
29
  const RegisterSlave = require('./register_slave');
30
+ const ResetConnection = require('./reset_connection');
30
31
  const ResultSetHeader = require('./resultset_header');
31
32
  const SSLRequest = require('./ssl_request');
32
33
  const TextRow = require('./text_row');
@@ -48,6 +49,7 @@ const ctorMap = {
48
49
  PreparedStatementHeader,
49
50
  Query,
50
51
  RegisterSlave,
52
+ ResetConnection,
51
53
  ResultSetHeader,
52
54
  SSLRequest,
53
55
  TextRow,
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const Packet = require('../packets/packet');
4
+ const CommandCodes = require('../constants/commands');
5
+
6
+ class ResetConnection {
7
+ constructor() {}
8
+
9
+ toPacket() {
10
+ const packet = new Packet(0, Buffer.alloc(5), 0, 5);
11
+ packet.offset = 4;
12
+ packet.writeInt8(CommandCodes.RESET_CONNECTION);
13
+ return packet;
14
+ }
15
+ }
16
+
17
+ module.exports = ResetConnection;
@@ -24,6 +24,10 @@ class PoolConfig {
24
24
  this.queueLimit = isNaN(options.queueLimit)
25
25
  ? 0
26
26
  : Number(options.queueLimit);
27
+ this.resetOnRelease =
28
+ options.resetOnRelease === undefined
29
+ ? false
30
+ : Boolean(options.resetOnRelease);
27
31
  }
28
32
  }
29
33
 
@@ -26,14 +26,13 @@ class PromiseConnection extends EventEmitter {
26
26
 
27
27
  query(query, params) {
28
28
  const c = this.connection;
29
- const localErr = new Error();
30
29
  if (typeof params === 'function') {
31
30
  throw new Error(
32
31
  'Callback function is not available with promise clients.'
33
32
  );
34
33
  }
35
34
  return new this.Promise((resolve, reject) => {
36
- const done = makeDoneCb(resolve, reject, localErr);
35
+ const done = makeDoneCb(resolve, reject);
37
36
  if (params !== undefined) {
38
37
  c.query(query, params, done);
39
38
  } else {
@@ -44,14 +43,13 @@ class PromiseConnection extends EventEmitter {
44
43
 
45
44
  execute(query, params) {
46
45
  const c = this.connection;
47
- const localErr = new Error();
48
46
  if (typeof params === 'function') {
49
47
  throw new Error(
50
48
  'Callback function is not available with promise clients.'
51
49
  );
52
50
  }
53
51
  return new this.Promise((resolve, reject) => {
54
- const done = makeDoneCb(resolve, reject, localErr);
52
+ const done = makeDoneCb(resolve, reject);
55
53
  if (params !== undefined) {
56
54
  c.execute(query, params, done);
57
55
  } else {
@@ -74,37 +72,34 @@ class PromiseConnection extends EventEmitter {
74
72
 
75
73
  beginTransaction() {
76
74
  const c = this.connection;
77
- const localErr = new Error();
78
75
  return new this.Promise((resolve, reject) => {
79
- const done = makeDoneCb(resolve, reject, localErr);
76
+ const done = makeDoneCb(resolve, reject);
80
77
  c.beginTransaction(done);
81
78
  });
82
79
  }
83
80
 
84
81
  commit() {
85
82
  const c = this.connection;
86
- const localErr = new Error();
87
83
  return new this.Promise((resolve, reject) => {
88
- const done = makeDoneCb(resolve, reject, localErr);
84
+ const done = makeDoneCb(resolve, reject);
89
85
  c.commit(done);
90
86
  });
91
87
  }
92
88
 
93
89
  rollback() {
94
90
  const c = this.connection;
95
- const localErr = new Error();
96
91
  return new this.Promise((resolve, reject) => {
97
- const done = makeDoneCb(resolve, reject, localErr);
92
+ const done = makeDoneCb(resolve, reject);
98
93
  c.rollback(done);
99
94
  });
100
95
  }
101
96
 
102
97
  ping() {
103
98
  const c = this.connection;
104
- const localErr = new Error();
105
99
  return new this.Promise((resolve, reject) => {
106
100
  c.ping((err) => {
107
101
  if (err) {
102
+ const localErr = new Error();
108
103
  localErr.message = err.message;
109
104
  localErr.code = err.code;
110
105
  localErr.errno = err.errno;
@@ -118,12 +113,31 @@ class PromiseConnection extends EventEmitter {
118
113
  });
119
114
  }
120
115
 
116
+ reset() {
117
+ const c = this.connection;
118
+ return new this.Promise((resolve, reject) => {
119
+ c.reset((err) => {
120
+ if (err) {
121
+ const localErr = new Error();
122
+ localErr.message = err.message;
123
+ localErr.code = err.code;
124
+ localErr.errno = err.errno;
125
+ localErr.sqlState = err.sqlState;
126
+ localErr.sqlMessage = err.sqlMessage;
127
+ reject(localErr);
128
+ } else {
129
+ resolve();
130
+ }
131
+ });
132
+ });
133
+ }
134
+
121
135
  connect() {
122
136
  const c = this.connection;
123
- const localErr = new Error();
124
137
  return new this.Promise((resolve, reject) => {
125
138
  c.connect((err, param) => {
126
139
  if (err) {
140
+ const localErr = new Error();
127
141
  localErr.message = err.message;
128
142
  localErr.code = err.code;
129
143
  localErr.errno = err.errno;
@@ -140,10 +154,10 @@ class PromiseConnection extends EventEmitter {
140
154
  prepare(options) {
141
155
  const c = this.connection;
142
156
  const promiseImpl = this.Promise;
143
- const localErr = new Error();
144
157
  return new this.Promise((resolve, reject) => {
145
158
  c.prepare(options, (err, statement) => {
146
159
  if (err) {
160
+ const localErr = new Error();
147
161
  localErr.message = err.message;
148
162
  localErr.code = err.code;
149
163
  localErr.errno = err.errno;
@@ -163,10 +177,10 @@ class PromiseConnection extends EventEmitter {
163
177
 
164
178
  changeUser(options) {
165
179
  const c = this.connection;
166
- const localErr = new Error();
167
180
  return new this.Promise((resolve, reject) => {
168
181
  c.changeUser(options, (err) => {
169
182
  if (err) {
183
+ const localErr = new Error();
170
184
  localErr.message = err.message;
171
185
  localErr.code = err.code;
172
186
  localErr.errno = err.errno;
@@ -1,8 +1,9 @@
1
1
  'use strict';
2
2
 
3
- function makeDoneCb(resolve, reject, localErr) {
3
+ function makeDoneCb(resolve, reject) {
4
4
  return function (err, rows, fields) {
5
5
  if (err) {
6
+ const localErr = new Error();
6
7
  localErr.message = err.message;
7
8
  localErr.code = err.code;
8
9
  localErr.errno = err.errno;
@@ -33,14 +33,13 @@ class PromisePool extends EventEmitter {
33
33
 
34
34
  query(sql, args) {
35
35
  const corePool = this.pool;
36
- const localErr = new Error();
37
36
  if (typeof args === 'function') {
38
37
  throw new Error(
39
38
  'Callback function is not available with promise clients.'
40
39
  );
41
40
  }
42
41
  return new this.Promise((resolve, reject) => {
43
- const done = makeDoneCb(resolve, reject, localErr);
42
+ const done = makeDoneCb(resolve, reject);
44
43
  if (args !== undefined) {
45
44
  corePool.query(sql, args, done);
46
45
  } else {
@@ -51,14 +50,13 @@ class PromisePool extends EventEmitter {
51
50
 
52
51
  execute(sql, args) {
53
52
  const corePool = this.pool;
54
- const localErr = new Error();
55
53
  if (typeof args === 'function') {
56
54
  throw new Error(
57
55
  'Callback function is not available with promise clients.'
58
56
  );
59
57
  }
60
58
  return new this.Promise((resolve, reject) => {
61
- const done = makeDoneCb(resolve, reject, localErr);
59
+ const done = makeDoneCb(resolve, reject);
62
60
  if (args) {
63
61
  corePool.execute(sql, args, done);
64
62
  } else {
@@ -69,10 +67,10 @@ class PromisePool extends EventEmitter {
69
67
 
70
68
  end() {
71
69
  const corePool = this.pool;
72
- const localErr = new Error();
73
70
  return new this.Promise((resolve, reject) => {
74
71
  corePool.end((err) => {
75
72
  if (err) {
73
+ const localErr = new Error();
76
74
  localErr.message = err.message;
77
75
  localErr.code = err.code;
78
76
  localErr.errno = err.errno;
@@ -24,28 +24,26 @@ class PromisePoolNamespace {
24
24
 
25
25
  query(sql, values) {
26
26
  const corePoolNamespace = this.poolNamespace;
27
- const localErr = new Error();
28
27
  if (typeof values === 'function') {
29
28
  throw new Error(
30
29
  'Callback function is not available with promise clients.'
31
30
  );
32
31
  }
33
32
  return new this.Promise((resolve, reject) => {
34
- const done = makeDoneCb(resolve, reject, localErr);
33
+ const done = makeDoneCb(resolve, reject);
35
34
  corePoolNamespace.query(sql, values, done);
36
35
  });
37
36
  }
38
37
 
39
38
  execute(sql, values) {
40
39
  const corePoolNamespace = this.poolNamespace;
41
- const localErr = new Error();
42
40
  if (typeof values === 'function') {
43
41
  throw new Error(
44
42
  'Callback function is not available with promise clients.'
45
43
  );
46
44
  }
47
45
  return new this.Promise((resolve, reject) => {
48
- const done = makeDoneCb(resolve, reject, localErr);
46
+ const done = makeDoneCb(resolve, reject);
49
47
  corePoolNamespace.execute(sql, values, done);
50
48
  });
51
49
  }
@@ -10,9 +10,8 @@ class PromisePreparedStatementInfo {
10
10
 
11
11
  execute(parameters) {
12
12
  const s = this.statement;
13
- const localErr = new Error();
14
13
  return new this.Promise((resolve, reject) => {
15
- const done = makeDoneCb(resolve, reject, localErr);
14
+ const done = makeDoneCb(resolve, reject);
16
15
  if (parameters) {
17
16
  s.execute(parameters, done);
18
17
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql2",
3
- "version": "3.21.2-canary.884bec56",
3
+ "version": "3.22.0",
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",
@@ -68,7 +68,7 @@
68
68
  "devDependencies": {
69
69
  "@eslint/eslintrc": "^3.3.3",
70
70
  "@eslint/js": "^9.39.2",
71
- "@eslint/markdown": "^7.5.1",
71
+ "@eslint/markdown": "^8.0.1",
72
72
  "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
73
73
  "@pokujs/multi-suite": "^1.0.0",
74
74
  "@rollup/plugin-commonjs": "^29.0.2",
package/promise.d.ts CHANGED
@@ -51,6 +51,8 @@ export declare class Connection extends QueryableAndExecutableBase {
51
51
 
52
52
  ping(): Promise<void>;
53
53
 
54
+ reset(): Promise<void>;
55
+
54
56
  beginTransaction(): Promise<void>;
55
57
 
56
58
  commit(): Promise<void>;
package/promise.js CHANGED
@@ -16,7 +16,6 @@ const PromisePoolNamespace = require('./lib/promise/pool_cluster');
16
16
 
17
17
  function createConnectionPromise(opts) {
18
18
  const coreConnection = createConnection(opts);
19
- const createConnectionErr = new Error();
20
19
  const thePromise = opts.Promise || Promise;
21
20
  if (!thePromise) {
22
21
  throw new Error(
@@ -30,6 +29,7 @@ function createConnectionPromise(opts) {
30
29
  resolve(new PromiseConnection(coreConnection, thePromise));
31
30
  });
32
31
  coreConnection.once('error', (err) => {
32
+ const createConnectionErr = new Error();
33
33
  createConnectionErr.message = err.message;
34
34
  createConnectionErr.code = err.code;
35
35
  createConnectionErr.errno = err.errno;
@@ -83,28 +83,26 @@ class PromisePoolCluster extends EventEmitter {
83
83
 
84
84
  query(sql, args) {
85
85
  const corePoolCluster = this.poolCluster;
86
- const localErr = new Error();
87
86
  if (typeof args === 'function') {
88
87
  throw new Error(
89
88
  'Callback function is not available with promise clients.'
90
89
  );
91
90
  }
92
91
  return new this.Promise((resolve, reject) => {
93
- const done = makeDoneCb(resolve, reject, localErr);
92
+ const done = makeDoneCb(resolve, reject);
94
93
  corePoolCluster.query(sql, args, done);
95
94
  });
96
95
  }
97
96
 
98
97
  execute(sql, args) {
99
98
  const corePoolCluster = this.poolCluster;
100
- const localErr = new Error();
101
99
  if (typeof args === 'function') {
102
100
  throw new Error(
103
101
  'Callback function is not available with promise clients.'
104
102
  );
105
103
  }
106
104
  return new this.Promise((resolve, reject) => {
107
- const done = makeDoneCb(resolve, reject, localErr);
105
+ const done = makeDoneCb(resolve, reject);
108
106
  corePoolCluster.execute(sql, args, done);
109
107
  });
110
108
  }
@@ -118,10 +116,10 @@ class PromisePoolCluster extends EventEmitter {
118
116
 
119
117
  end() {
120
118
  const corePoolCluster = this.poolCluster;
121
- const localErr = new Error();
122
119
  return new this.Promise((resolve, reject) => {
123
120
  corePoolCluster.end((err) => {
124
121
  if (err) {
122
+ const localErr = new Error();
125
123
  localErr.message = err.message;
126
124
  localErr.code = err.code;
127
125
  localErr.errno = err.errno;
@@ -438,6 +438,8 @@ declare class Connection extends QueryableBase(ExecutableBase(EventEmitter)) {
438
438
 
439
439
  ping(callback?: (err: QueryError | null) => any): void;
440
440
 
441
+ reset(callback?: (err: QueryError | null) => any): void;
442
+
441
443
  writeOk(args?: OkPacketParams): void;
442
444
 
443
445
  writeError(args?: ErrorPacketParams): void;
@@ -37,6 +37,13 @@ export interface PoolOptions extends ConnectionOptions {
37
37
  * is no limit to the number of queued connection requests. (Default: 0)
38
38
  */
39
39
  queueLimit?: number;
40
+
41
+ /**
42
+ * Whether to reset the connection state (user variables, temporary tables, transactions, etc.) when
43
+ * releasing the connection back to the pool. This ensures each connection starts clean for the next user.
44
+ * Requires MySQL 5.7.3+. (Default: false)
45
+ */
46
+ resetOnRelease?: boolean;
40
47
  }
41
48
 
42
49
  declare class Pool extends QueryableBase(ExecutableBase(EventEmitter)) {