mysql2 3.7.0 → 3.8.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.
@@ -279,7 +279,7 @@ class Query extends Command {
279
279
  });
280
280
  this.on('end', () => {
281
281
  stream.push(null); // pushing null, indicating EOF
282
- stream.emit('close'); // notify readers that query has completed
282
+ setImmediate(() => stream.emit('close')); // notify readers that query has completed
283
283
  });
284
284
  this.on('fields', fields => {
285
285
  stream.emit('fields', fields); // replicate old emitter
package/lib/connection.js CHANGED
@@ -362,6 +362,9 @@ class Connection extends EventEmitter {
362
362
  const secureSocket = Tls.connect({
363
363
  rejectUnauthorized,
364
364
  requestCert: rejectUnauthorized,
365
+ checkServerIdentity: verifyIdentity
366
+ ? Tls.checkServerIdentity
367
+ : function() { return undefined; },
365
368
  secureContext,
366
369
  isServer: false,
367
370
  socket: this.stream,
@@ -1,13 +1,34 @@
1
1
  'use strict';
2
2
 
3
3
  const Iconv = require('iconv-lite');
4
+ const LRU = require('lru-cache').default;
4
5
 
5
- exports.decode = function(buffer, encoding, start, end, options) {
6
+ const decoderCache = new LRU({
7
+ max: 500,
8
+ });
9
+
10
+ exports.decode = function (buffer, encoding, start, end, options) {
6
11
  if (Buffer.isEncoding(encoding)) {
7
12
  return buffer.toString(encoding, start, end);
8
13
  }
9
14
 
10
- const decoder = Iconv.getDecoder(encoding, options || {});
15
+ // Optimize for common case: encoding="short_string", options=undefined.
16
+ let decoder;
17
+ if (!options) {
18
+ decoder = decoderCache.get(encoding);
19
+ if (!decoder) {
20
+ decoder = Iconv.getDecoder(encoding);
21
+ decoderCache.set(encoding, decoder);
22
+ }
23
+ } else {
24
+ const decoderArgs = { encoding, options };
25
+ const decoderKey = JSON.stringify(decoderArgs);
26
+ decoder = decoderCache.get(decoderKey);
27
+ if (!decoder) {
28
+ decoder = Iconv.getDecoder(decoderArgs.encoding, decoderArgs.options);
29
+ decoderCache.set(decoderKey, decoder);
30
+ }
31
+ }
11
32
 
12
33
  const res = decoder.write(buffer.slice(start, end));
13
34
  const trail = decoder.end();
@@ -15,7 +36,7 @@ exports.decode = function(buffer, encoding, start, end, options) {
15
36
  return trail ? res + trail : res;
16
37
  };
17
38
 
18
- exports.encode = function(string, encoding, options) {
39
+ exports.encode = function (string, encoding, options) {
19
40
  if (Buffer.isEncoding(encoding)) {
20
41
  return Buffer.from(string, encoding);
21
42
  }
package/lib/pool.js CHANGED
@@ -100,6 +100,7 @@ class Pool extends EventEmitter {
100
100
 
101
101
  end(cb) {
102
102
  this._closed = true;
103
+ clearTimeout(this._removeIdleTimeoutConnectionsTimer);
103
104
  if (typeof cb !== 'function') {
104
105
  cb = function(err) {
105
106
  if (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql2",
3
- "version": "3.7.0",
3
+ "version": "3.8.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",
@@ -70,7 +70,7 @@
70
70
  "@typescript-eslint/parser": "^5.42.1",
71
71
  "assert-diff": "^3.0.2",
72
72
  "benchmark": "^2.1.4",
73
- "c8": "^8.0.0",
73
+ "c8": "^9.0.0",
74
74
  "error-stack-parser": "^2.0.3",
75
75
  "eslint": "^8.27.0",
76
76
  "eslint-config-prettier": "^9.0.0",
@@ -19,6 +19,7 @@ import { Connection as PromiseConnection } from '../../../promise.js';
19
19
  import { AuthPlugin } from './Auth.js';
20
20
  import { QueryableBase } from './protocol/sequences/QueryableBase.js';
21
21
  import { ExecutableBase } from './protocol/sequences/ExecutableBase.js';
22
+ import { TypeCast } from './parsers/typeCast.js';
22
23
 
23
24
  export interface SslOptions {
24
25
  /**
@@ -172,26 +173,48 @@ export interface ConnectionOptions {
172
173
  infileStreamFactory?: (path: string) => Readable;
173
174
 
174
175
  /**
175
- * Determines if column values should be converted to native JavaScript types. It is not recommended (and may go away / change in the future)
176
- * to disable type casting, but you can currently do so on either the connection or query level. (Default: true)
176
+ * Determines if column values should be converted to native JavaScript types.
177
177
  *
178
- * You can also specify a function (field: any, next: () => void) => {} to do the type casting yourself.
178
+ * @default true
179
179
  *
180
- * WARNING: YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once.
180
+ * It is not recommended (and may go away / change in the future) to disable type casting, but you can currently do so on either the connection or query level.
181
181
  *
182
- * field.string()
183
- * field.buffer()
184
- * field.geometry()
182
+ * ---
185
183
  *
186
- * are aliases for
184
+ * You can also specify a function to do the type casting yourself:
185
+ * ```ts
186
+ * (field: Field, next: () => void) => {
187
+ * return next();
188
+ * }
189
+ * ```
187
190
  *
188
- * parser.parseLengthCodedString()
189
- * parser.parseLengthCodedBuffer()
190
- * parser.parseGeometryValue()
191
+ * ---
191
192
  *
192
- * You can find which field function you need to use by looking at: RowDataPacket.prototype._typeCast
193
+ * **WARNING:**
194
+ *
195
+ * YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once:
196
+ *
197
+ * ```js
198
+ * field.string();
199
+ * field.buffer();
200
+ * field.geometry();
201
+ * ```
202
+
203
+ * Which are aliases for:
204
+ *
205
+ * ```js
206
+ * parser.parseLengthCodedString();
207
+ * parser.parseLengthCodedBuffer();
208
+ * parser.parseGeometryValue();
209
+ * ```
210
+ *
211
+ * You can find which field function you need to use by looking at `RowDataPacket.prototype._typeCast`.
212
+ *
213
+ * ---
214
+ *
215
+ * For `execute`, please see: [typeCast not supported with .execute #649](https://github.com/sidorares/node-mysql2/issues/649).
193
216
  */
194
- typeCast?: boolean | ((field: any, next: () => void) => any);
217
+ typeCast?: TypeCast;
195
218
 
196
219
  /**
197
220
  * A custom query format function
@@ -0,0 +1,53 @@
1
+ type Geometry = {
2
+ x: number;
3
+ y: number;
4
+ };
5
+
6
+ type Type = {
7
+ type:
8
+ | 'DECIMAL'
9
+ | 'TINY'
10
+ | 'SHORT'
11
+ | 'LONG'
12
+ | 'FLOAT'
13
+ | 'DOUBLE'
14
+ | 'NULL'
15
+ | 'TIMESTAMP'
16
+ | 'TIMESTAMP2'
17
+ | 'LONGLONG'
18
+ | 'INT24'
19
+ | 'DATE'
20
+ | 'TIME'
21
+ | 'TIME2'
22
+ | 'DATETIME'
23
+ | 'DATETIME2'
24
+ | 'YEAR'
25
+ | 'NEWDATE'
26
+ | 'VARCHAR'
27
+ | 'BIT'
28
+ | 'JSON'
29
+ | 'NEWDECIMAL'
30
+ | 'ENUM'
31
+ | 'SET'
32
+ | 'TINY_BLOB'
33
+ | 'MEDIUM_BLOB'
34
+ | 'LONG_BLOB'
35
+ | 'BLOB'
36
+ | 'VAR_STRING'
37
+ | 'STRING'
38
+ | 'GEOMETRY';
39
+ };
40
+
41
+ type Field = Type & {
42
+ length: number;
43
+ db: string;
44
+ table: string;
45
+ name: string;
46
+ string: () => string | null;
47
+ buffer: () => Buffer | null;
48
+ geometry: () => Geometry | Geometry[] | null;
49
+ };
50
+
51
+ type Next = () => void;
52
+
53
+ export type TypeCast = ((field: Field, next: Next) => any) | boolean;
@@ -1,6 +1,7 @@
1
1
  import { Sequence } from './Sequence.js';
2
2
  import { OkPacket, RowDataPacket, FieldPacket } from '../packets/index.js';
3
3
  import { Readable } from 'stream';
4
+ import { TypeCast } from '../../parsers/typeCast.js';
4
5
 
5
6
  export interface QueryOptions {
6
7
  /**
@@ -33,26 +34,48 @@ export interface QueryOptions {
33
34
  nestTables?: any;
34
35
 
35
36
  /**
36
- * Determines if column values should be converted to native JavaScript types. It is not recommended (and may go away / change in the future)
37
- * to disable type casting, but you can currently do so on either the connection or query level. (Default: true)
37
+ * Determines if column values should be converted to native JavaScript types.
38
38
  *
39
- * You can also specify a function (field: any, next: () => void) => {} to do the type casting yourself.
39
+ * @default true
40
40
  *
41
- * WARNING: YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once.
41
+ * It is not recommended (and may go away / change in the future) to disable type casting, but you can currently do so on either the connection or query level.
42
42
  *
43
- * field.string()
44
- * field.buffer()
45
- * field.geometry()
43
+ * ---
46
44
  *
47
- * are aliases for
45
+ * You can also specify a function to do the type casting yourself:
46
+ * ```ts
47
+ * (field: Field, next: () => void) => {
48
+ * return next();
49
+ * }
50
+ * ```
48
51
  *
49
- * parser.parseLengthCodedString()
50
- * parser.parseLengthCodedBuffer()
51
- * parser.parseGeometryValue()
52
+ * ---
52
53
  *
53
- * You can find which field function you need to use by looking at: RowDataPacket.prototype._typeCast
54
+ * **WARNING:**
55
+ *
56
+ * YOU MUST INVOKE the parser using one of these three field functions in your custom typeCast callback. They can only be called once:
57
+ *
58
+ * ```js
59
+ * field.string();
60
+ * field.buffer();
61
+ * field.geometry();
62
+ * ```
63
+
64
+ * Which are aliases for:
65
+ *
66
+ * ```js
67
+ * parser.parseLengthCodedString();
68
+ * parser.parseLengthCodedBuffer();
69
+ * parser.parseGeometryValue();
70
+ * ```
71
+ *
72
+ * You can find which field function you need to use by looking at `RowDataPacket.prototype._typeCast`.
73
+ *
74
+ * ---
75
+ *
76
+ * For `execute`, please see: [typeCast not supported with .execute #649](https://github.com/sidorares/node-mysql2/issues/649).
54
77
  */
55
- typeCast?: any;
78
+ typeCast?: TypeCast;
56
79
 
57
80
  /**
58
81
  * This overrides the same option set at the connection level.
@@ -137,11 +160,11 @@ declare class Query extends Sequence {
137
160
  on(event: 'error', listener: (err: QueryError) => any): this;
138
161
  on(
139
162
  event: 'fields',
140
- listener: (fields: FieldPacket, index: number) => any
163
+ listener: (fields: FieldPacket, index: number) => any,
141
164
  ): this;
142
165
  on(
143
166
  event: 'result',
144
- listener: (result: RowDataPacket | OkPacket, index: number) => any
167
+ listener: (result: RowDataPacket | OkPacket, index: number) => any,
145
168
  ): this;
146
169
  on(event: 'end', listener: () => any): this;
147
170
  }