mysql2 3.17.1 → 3.17.3

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/pool.js CHANGED
@@ -6,6 +6,22 @@ const EventEmitter = require('events').EventEmitter;
6
6
  const PoolConnection = require('../pool_connection.js');
7
7
  const Queue = require('denque');
8
8
  const BaseConnection = require('./connection.js');
9
+ const Errors = require('../constants/errors.js');
10
+
11
+ // Source: https://github.com/go-sql-driver/mysql/blob/76c00e35a8d48f8f70f0e7dffe584692bd3fa612/packets.go#L598-L613
12
+ function isReadOnlyError(err) {
13
+ if (!err || !err.errno) {
14
+ return false;
15
+ }
16
+ // 1792: ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
17
+ // 1290: ER_OPTION_PREVENTS_STATEMENT (returned by Aurora during failover)
18
+ // 1836: ER_READ_ONLY_MODE
19
+ return (
20
+ err.errno === Errors.ER_OPTION_PREVENTS_STATEMENT ||
21
+ err.errno === Errors.ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION ||
22
+ err.errno === Errors.ER_READ_ONLY_MODE
23
+ );
24
+ }
9
25
 
10
26
  function spliceConnection(queue, connection) {
11
27
  const len = queue.length;
@@ -146,8 +162,24 @@ class BasePool extends EventEmitter {
146
162
  return;
147
163
  }
148
164
  try {
165
+ let queryError = null;
166
+ const origOnResult = cmdQuery.onResult;
167
+ if (origOnResult) {
168
+ cmdQuery.onResult = function (err, rows, fields) {
169
+ queryError = err || null;
170
+ origOnResult(err, rows, fields);
171
+ };
172
+ } else {
173
+ cmdQuery.once('error', (err) => {
174
+ queryError = err;
175
+ });
176
+ }
149
177
  conn.query(cmdQuery).once('end', () => {
150
- conn.release();
178
+ if (isReadOnlyError(queryError)) {
179
+ conn.destroy();
180
+ } else {
181
+ conn.release();
182
+ }
151
183
  });
152
184
  } catch (e) {
153
185
  conn.release();
@@ -169,9 +201,16 @@ class BasePool extends EventEmitter {
169
201
  return cb(err);
170
202
  }
171
203
  try {
172
- conn.execute(sql, values, cb).once('end', () => {
173
- conn.release();
174
- });
204
+ conn
205
+ .execute(sql, values, (err, rows, fields) => {
206
+ if (isReadOnlyError(err)) {
207
+ conn.destroy();
208
+ }
209
+ cb(err, rows, fields);
210
+ })
211
+ .once('end', () => {
212
+ conn.release();
213
+ });
175
214
  } catch (e) {
176
215
  conn.release();
177
216
  return cb(e);
@@ -29,10 +29,10 @@ class BasePoolConnection extends BaseConnection {
29
29
  this._pool.releaseConnection(this);
30
30
  }
31
31
 
32
- end() {
32
+ end(callback) {
33
33
  if (this.config.gracefulEnd) {
34
34
  this._removeFromPool();
35
- super.end();
35
+ super.end(callback);
36
36
 
37
37
  return;
38
38
  }
@@ -46,6 +46,9 @@ class BasePoolConnection extends BaseConnection {
46
46
  this.emit('warn', err);
47
47
  console.warn(err.message);
48
48
  this.release();
49
+ if (typeof callback === 'function') {
50
+ callback();
51
+ }
49
52
  }
50
53
 
51
54
  destroy() {
@@ -6,6 +6,32 @@
6
6
  const zlib = require('zlib');
7
7
  const PacketParser = require('./packet_parser.js');
8
8
 
9
+ class Queue {
10
+ constructor() {
11
+ this._queue = [];
12
+ this._running = false;
13
+ }
14
+
15
+ push(fn) {
16
+ this._queue.push(fn);
17
+ if (!this._running) {
18
+ this._running = true;
19
+ process.nextTick(() => this._next());
20
+ }
21
+ }
22
+
23
+ _next() {
24
+ const task = this._queue.shift();
25
+ if (!task) {
26
+ this._running = false;
27
+ return;
28
+ }
29
+ task({
30
+ done: () => process.nextTick(() => this._next()),
31
+ });
32
+ }
33
+ }
34
+
9
35
  function handleCompressedPacket(packet) {
10
36
  // eslint-disable-next-line consistent-this, no-invalid-this
11
37
  const connection = this;
@@ -117,11 +143,11 @@ function enableCompression(connection) {
117
143
  connection.writeUncompressed = connection.write;
118
144
  connection.write = writeCompressed;
119
145
 
120
- const seqqueue = require('seq-queue');
121
- connection.inflateQueue = seqqueue.createQueue();
122
- connection.deflateQueue = seqqueue.createQueue();
146
+ connection.inflateQueue = new Queue();
147
+ connection.deflateQueue = new Queue();
123
148
  }
124
149
 
125
150
  module.exports = {
126
151
  enableCompression: enableCompression,
152
+ Queue: Queue,
127
153
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql2",
3
- "version": "3.17.1",
3
+ "version": "3.17.3",
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,17 +8,22 @@
8
8
  "scripts": {
9
9
  "lint": "eslint . && prettier --check .",
10
10
  "lint:fix": "eslint . --fix && prettier --write .",
11
- "test": "poku -d -r=verbose --sequential test/esm test/unit test/integration",
12
- "test:bun": "bun poku -d --sequential test/esm test/unit test/integration",
13
- "test:deno": "deno run --allow-read --allow-env --allow-run npm:poku -d --sequential --denoAllow=\"read,env,net,sys\" test/esm test/unit test/integration",
14
- "test:tsc-build": "cd \"test/tsc-build\" && npx tsc -p \"tsconfig.json\"",
11
+ "test": "npm run test:parallel && npm run test:global",
12
+ "test:parallel": "poku -c=\"poku.config.mjs\" test/esm",
13
+ "test:global": "cross-env SUITE=global poku -c=\"poku.config.mjs\" test/esm/global",
14
+ "test:bun": "npm run test:bun:parallel",
15
+ "test:bun:parallel": "bun poku -c=\"poku.config.mjs\" test/esm",
16
+ "test:deno": "npm run test:deno:parallel && npm run test:deno:global",
17
+ "test:deno:parallel": "deno run --allow-read --allow-env --allow-run npm:poku@canary -c=\"poku.config.mjs\" test/esm",
18
+ "test:deno:global": "cross-env SUITE=global deno run --allow-read --allow-env --allow-run npm:poku@canary -c=\"poku.config.mjs\" test/esm/global",
15
19
  "test:docker:up": "docker compose -f test/docker-compose.yml up --abort-on-container-exit --remove-orphans",
16
20
  "test:docker:down": "docker compose -f test/docker-compose.yml down",
17
21
  "test:docker:node": "npm run test:docker:up -- node && npm run test:docker:down",
18
22
  "test:docker:bun": "npm run test:docker:up -- bun && npm run test:docker:down",
19
23
  "test:docker:deno": "npm run test:docker:up -- deno && npm run test:docker:down",
20
24
  "test:docker:coverage": "npm run test:docker:up -- coverage && npm run test:docker:down",
21
- "coverage-test": "c8 npm run test",
25
+ "test:coverage": "c8 npm test",
26
+ "typecheck": "cd \"test/tsc-build\" && tsc -p \"tsconfig.json\" && cd ../esm && tsc -p \"tsconfig.json\" --noEmit",
22
27
  "benchmark": "node ./benchmarks/benchmark.js",
23
28
  "wait-port": "wait-on"
24
29
  },
@@ -57,30 +62,31 @@
57
62
  "generate-function": "^2.3.1",
58
63
  "iconv-lite": "^0.7.2",
59
64
  "long": "^5.3.2",
60
- "lru.min": "^1.1.3",
65
+ "lru.min": "^1.1.4",
61
66
  "named-placeholders": "^1.1.6",
62
- "seq-queue": "^0.0.5",
63
- "sql-escaper": "^1.3.2"
67
+ "sql-escaper": "^1.3.3"
64
68
  },
65
69
  "devDependencies": {
66
70
  "@eslint/eslintrc": "^3.3.3",
67
71
  "@eslint/js": "^9.39.2",
68
72
  "@eslint/markdown": "^7.5.1",
69
- "@types/node": "^25.0.9",
70
- "@typescript-eslint/eslint-plugin": "^8.53.0",
71
- "@typescript-eslint/parser": "^8.53.0",
73
+ "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
74
+ "@types/node": "^25.3.0",
75
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
76
+ "@typescript-eslint/parser": "^8.56.0",
72
77
  "assert-diff": "^3.0.4",
73
78
  "benchmark": "^2.1.4",
74
79
  "c8": "^10.1.3",
80
+ "cross-env": "^10.1.0",
75
81
  "error-stack-parser": "^2.1.4",
76
82
  "eslint-config-prettier": "^10.1.8",
77
83
  "eslint-plugin-async-await": "^0.0.0",
78
- "eslint-plugin-markdown": "^5.1.0",
79
84
  "eslint-plugin-prettier": "^5.5.5",
80
- "globals": "^17.0.0",
81
- "poku": "^3.0.2",
85
+ "globals": "^17.3.0",
86
+ "poku": "^3.0.3-canary.8f374795",
82
87
  "portfinder": "^1.0.38",
83
- "prettier": "^3.8.0",
88
+ "prettier": "^3.8.1",
89
+ "tsx": "^4.21.0",
84
90
  "typescript": "^5.9.3"
85
91
  }
86
92
  }