@depup/mysql2 3.23.4-depup.0 → 3.24.0-depup.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.
package/README.md CHANGED
@@ -13,8 +13,8 @@ npm install @depup/mysql2
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [mysql2](https://www.npmjs.com/package/mysql2) @ 3.23.4 |
17
- | Processed | 2026-08-20 |
16
+ | Original | [mysql2](https://www.npmjs.com/package/mysql2) @ 3.24.0 |
17
+ | Processed | 2026-08-24 |
18
18
  | Smoke test | passed |
19
19
  | Deps updated | 0 |
20
20
 
package/changes.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "bumped": {},
3
- "timestamp": "2026-08-20T08:13:41.208Z",
3
+ "timestamp": "2026-08-24T00:15:42.327Z",
4
4
  "totalUpdated": 0
5
5
  }
package/index.js CHANGED
@@ -60,6 +60,11 @@ exports.__defineGetter__(
60
60
 
61
61
  exports.__defineGetter__('Types', () => require('./lib/constants/types.js'));
62
62
 
63
+ exports.__defineGetter__(
64
+ 'TypedParameter',
65
+ () => require('./lib/packets/typed_parameter.js').types
66
+ );
67
+
63
68
  exports.__defineGetter__('Charsets', () =>
64
69
  require('./lib/constants/charsets.js')
65
70
  );
@@ -496,7 +496,9 @@ class BaseConnection extends EventEmitter {
496
496
 
497
497
  handlePacket(packet) {
498
498
  if (this._paused) {
499
- this._paused_packets.push(packet);
499
+ // the parser reuses its packet instance; keep a stable copy when
500
+ // queueing for later
501
+ this._paused_packets.push(packet ? packet.clone() : packet);
500
502
  return;
501
503
  }
502
504
  if (this.config.debug) {
@@ -22,6 +22,8 @@ class Execute extends Command {
22
22
  this.queryTimeout = null;
23
23
  this._rows = [];
24
24
  this._fields = [];
25
+ this._currentRows = null;
26
+ this._currentFields = null;
25
27
  this._result = [];
26
28
  this._fieldCount = 0;
27
29
  this._rowParser = null;
@@ -54,7 +56,8 @@ class Execute extends Command {
54
56
  connection.config.timezone,
55
57
  this._executeOptions.attributes,
56
58
  clientFlags,
57
- connection._isMariaDB
59
+ connection._isMariaDB,
60
+ this.statement.parameters
58
61
  );
59
62
  //For reasons why this try-catch is here, please see
60
63
  // https://github.com/sidorares/node-mysql2/pull/689
@@ -33,6 +33,8 @@ class Query extends Command {
33
33
  this._rowParser = null;
34
34
  this._fields = [];
35
35
  this._rows = [];
36
+ this._currentRows = null;
37
+ this._currentFields = null;
36
38
  this._receivedFieldsCount = 0;
37
39
  this._resultIndex = 0;
38
40
  this._localStream = null;
@@ -137,8 +139,10 @@ class Query extends Command {
137
139
  return this._streamLocalInfile(connection, rs.infileName);
138
140
  }
139
141
  this._receivedFieldsCount = 0;
140
- this._rows.push([]);
141
- this._fields.push([]);
142
+ this._currentRows = [];
143
+ this._currentFields = [];
144
+ this._rows.push(this._currentRows);
145
+ this._fields.push(this._currentFields);
142
146
  return this.readField;
143
147
  }
144
148
 
@@ -252,17 +256,13 @@ class Query extends Command {
252
256
  }
253
257
  let row;
254
258
  try {
255
- row = this._rowParser.next(
256
- packet,
257
- this._fields[this._resultIndex],
258
- this.options
259
- );
259
+ row = this._rowParser.next(packet, this._currentFields, this.options);
260
260
  } catch (err) {
261
261
  this._localStreamError = err;
262
262
  return this.doneInsert(null);
263
263
  }
264
264
  if (this.onResult) {
265
- this._rows[this._resultIndex].push(row);
265
+ this._currentRows.push(row);
266
266
  } else {
267
267
  this.emit('result', row, this._resultIndex);
268
268
  }
@@ -36,6 +36,9 @@ function handleCompressedPacket(packet) {
36
36
  const connection = this;
37
37
  const deflatedLength = packet.readInt24();
38
38
  const body = packet.readBuffer();
39
+ // the packet parser reuses its packet instance, so everything needed after
40
+ // the queued (asynchronous) inflate step must be read out now
41
+ const numPackets = packet.numPackets;
39
42
 
40
43
  if (deflatedLength !== 0) {
41
44
  connection.inflateQueue.push((task) => {
@@ -44,14 +47,14 @@ function handleCompressedPacket(packet) {
44
47
  connection._handleNetworkError(err);
45
48
  return;
46
49
  }
47
- connection._bumpCompressedSequenceId(packet.numPackets);
50
+ connection._bumpCompressedSequenceId(numPackets);
48
51
  connection._inflatedPacketsParser.execute(data);
49
52
  task.done();
50
53
  });
51
54
  });
52
55
  } else {
53
56
  connection.inflateQueue.push((task) => {
54
- connection._bumpCompressedSequenceId(packet.numPackets);
57
+ connection._bumpCompressedSequenceId(numPackets);
55
58
  connection._inflatedPacketsParser.execute(body);
56
59
  task.done();
57
60
  });
@@ -18,6 +18,7 @@ module.exports = {
18
18
  0x0e: 'NEWDATE', // aka ?
19
19
  0x0f: 'VARCHAR', // aka VARCHAR (?)
20
20
  0x10: 'BIT', // aka BIT, 1-8 byte
21
+ 0xf2: 'VECTOR',
21
22
  0xf5: 'JSON',
22
23
  0xf6: 'NEWDECIMAL', // aka DECIMAL
23
24
  0xf7: 'ENUM', // aka ENUM
@@ -33,6 +33,10 @@ class PacketParser {
33
33
  this.largePacketParts = [];
34
34
  this.firstPacketSequenceId = 0;
35
35
  this.onPacket = onPacket;
36
+ // complete packets are handed to onPacket through this single mutable
37
+ // instance; consumers that keep a packet past the synchronous callback
38
+ // (e.g. a paused connection) must clone() it
39
+ this._reusablePacket = new Packet(0, Buffer.allocUnsafe(4), 0, 4);
36
40
  this.execute = PacketParser.prototype.executeStart;
37
41
  this._flushLargePacket =
38
42
  packetHeaderLength === 7
@@ -72,14 +76,14 @@ class PacketParser {
72
76
  this.length < MAX_PACKET_LENGTH &&
73
77
  this.largePacketParts.length === 0
74
78
  ) {
75
- this.onPacket(
76
- new Packet(
77
- sequenceId,
78
- chunk,
79
- start,
80
- start + this.packetHeaderLength + this.length
81
- )
82
- );
79
+ const packet = this._reusablePacket;
80
+ packet.sequenceId = sequenceId;
81
+ packet.numPackets = 1;
82
+ packet.buffer = chunk;
83
+ packet.start = start;
84
+ packet.offset = start + 4;
85
+ packet.end = start + this.packetHeaderLength + this.length;
86
+ this.onPacket(packet);
83
87
  } else {
84
88
  // first large packet - remember it's id
85
89
  if (this.largePacketParts.length === 0) {
@@ -136,14 +140,14 @@ class PacketParser {
136
140
  this.length < MAX_PACKET_LENGTH &&
137
141
  this.largePacketParts.length === 0
138
142
  ) {
139
- this.onPacket(
140
- new Packet(
141
- sequenceId,
142
- payload,
143
- 0,
144
- this.length + this.packetHeaderLength
145
- )
146
- );
143
+ const packet = this._reusablePacket;
144
+ packet.sequenceId = sequenceId;
145
+ packet.numPackets = 1;
146
+ packet.buffer = payload;
147
+ packet.start = 0;
148
+ packet.offset = 4;
149
+ packet.end = this.length + this.packetHeaderLength;
150
+ this.onPacket(packet);
147
151
  } else {
148
152
  // first large packet - remember it's id
149
153
  if (this.largePacketParts.length === 0) {
@@ -288,24 +288,25 @@ class ColumnDefinition {
288
288
  }
289
289
 
290
290
  const addString = function (name) {
291
+ const cacheKey = `_${name}Value`;
292
+ const startKey = `_${name}Start`;
293
+ const lengthKey = `_${name}Length`;
294
+ ColumnDefinition.prototype[cacheKey] = undefined;
291
295
  Object.defineProperty(ColumnDefinition.prototype, name, {
292
296
  get: function () {
293
- const start = this[`_${name}Start`];
294
- const end = start + this[`_${name}Length`];
297
+ const cached = this[cacheKey];
298
+ if (cached !== undefined) {
299
+ return cached;
300
+ }
301
+ const start = this[startKey];
302
+ const end = start + this[lengthKey];
295
303
  const val = StringParser.decode(
296
304
  this._buf,
297
305
  this.encoding === 'binary' ? this._clientEncoding : this.encoding,
298
306
  start,
299
307
  end
300
308
  );
301
-
302
- Object.defineProperty(this, name, {
303
- value: val,
304
- writable: false,
305
- configurable: false,
306
- enumerable: false,
307
- });
308
-
309
+ this[cacheKey] = val;
309
310
  return val;
310
311
  },
311
312
  });
@@ -2,6 +2,13 @@
2
2
 
3
3
  const Types = require('../constants/types');
4
4
  const Packet = require('../packets/packet');
5
+ const StringParser = require('../parsers/string.js');
6
+ const {
7
+ TypedParameter,
8
+ encodeTypedParameter,
9
+ integerHint,
10
+ } = require('./typed_parameter.js');
11
+ const FieldFlags = require('../constants/field_flags.js');
5
12
 
6
13
  function isJSON(value) {
7
14
  return (
@@ -11,12 +18,23 @@ function isJSON(value) {
11
18
  );
12
19
  }
13
20
 
14
- function toParameter(value, encoding, timezone, jsonAsString) {
21
+ function toParameter(value, encoding, timezone, jsonAsString, hint) {
22
+ if (value instanceof TypedParameter) {
23
+ return encodeTypedParameter(value, encoding, timezone, jsonAsString);
24
+ }
25
+ if (hint) {
26
+ const hinted = integerHint(
27
+ value,
28
+ hint.columnType,
29
+ Boolean(hint.flags & FieldFlags.UNSIGNED)
30
+ );
31
+ if (hinted) {
32
+ return encodeTypedParameter(hinted, encoding, timezone, jsonAsString);
33
+ }
34
+ }
15
35
  let type = Types.VAR_STRING;
16
36
  let length;
17
- let writer = function (value) {
18
- return Packet.prototype.writeLengthCodedString.call(this, value, encoding);
19
- };
37
+ let writer = Packet.prototype.writeLengthCodedBuffer;
20
38
  if (value !== null) {
21
39
  switch (typeof value) {
22
40
  case 'undefined':
@@ -67,11 +85,23 @@ function toParameter(value, encoding, timezone, jsonAsString) {
67
85
  } else {
68
86
  value = '';
69
87
  type = Types.NULL;
88
+ length = 0;
89
+ writer = writeNothing;
70
90
  }
71
- if (!length) {
72
- length = Packet.lengthCodedStringLength(value, encoding);
91
+ if (length === undefined) {
92
+ value = StringParser.encode(value, encoding);
93
+ length = Packet.lengthCodedNumberLength(value.length) + value.length;
73
94
  }
74
- return { value, type, length, writer };
95
+ return {
96
+ value,
97
+ type,
98
+ length,
99
+ writer,
100
+ unsigned: false,
101
+ isNull: type === Types.NULL,
102
+ };
75
103
  }
76
104
 
105
+ function writeNothing() {}
106
+
77
107
  module.exports = { toParameter, isJSON };
@@ -5,6 +5,7 @@ const CommandCodes = require('../constants/commands');
5
5
  const ClientConstants = require('../constants/client');
6
6
  const Types = require('../constants/types');
7
7
  const Packet = require('../packets/packet');
8
+ const StringParser = require('../parsers/string.js');
8
9
  const CharsetToEncoding = require('../constants/charset_encodings.js');
9
10
  const { toParameter } = require('./encode_parameter.js');
10
11
 
@@ -16,7 +17,8 @@ class Execute {
16
17
  timezone,
17
18
  attributes,
18
19
  clientFlags,
19
- jsonAsString
20
+ jsonAsString,
21
+ parameterDefinitions
20
22
  ) {
21
23
  this.id = id;
22
24
  this.parameters = parameters;
@@ -25,6 +27,7 @@ class Execute {
25
27
  this.attributes = attributes;
26
28
  this.clientFlags = clientFlags || 0;
27
29
  this.jsonAsString = jsonAsString || false;
30
+ this.parameterDefinitions = parameterDefinitions || [];
28
31
  }
29
32
 
30
33
  static fromPacket(packet, encoding) {
@@ -95,7 +98,7 @@ class Execute {
95
98
  return { stmtId, flags, iterationCount, values };
96
99
  }
97
100
 
98
- _serializeToBuffer(buffer) {
101
+ toPacket() {
99
102
  const useQueryAttributes =
100
103
  this.clientFlags & ClientConstants.CLIENT_QUERY_ATTRIBUTES;
101
104
 
@@ -105,7 +108,53 @@ class Execute {
105
108
  const numAttrs = attrNames.length;
106
109
  const totalParams = numParams + numAttrs;
107
110
 
108
- const packet = new Packet(0, buffer, 0, buffer.length);
111
+ // packet header, command, statement id, cursor flags, iteration count
112
+ let length = 14;
113
+ if (useQueryAttributes) {
114
+ length += Packet.lengthCodedNumberLength(totalParams);
115
+ }
116
+
117
+ let allParams = null;
118
+ let attrNameBuffers = null;
119
+ if (totalParams > 0) {
120
+ allParams = new Array(totalParams);
121
+ for (let i = 0; i < numParams; i++) {
122
+ allParams[i] = toParameter(
123
+ this.parameters[i],
124
+ this.encoding,
125
+ this.timezone,
126
+ this.jsonAsString,
127
+ this.parameterDefinitions[i]
128
+ );
129
+ }
130
+ for (let i = 0; i < numAttrs; i++) {
131
+ allParams[numParams + i] = toParameter(
132
+ this.attributes[attrNames[i]],
133
+ this.encoding,
134
+ this.timezone
135
+ );
136
+ }
137
+
138
+ // null bitmap, new-params-bound flag, type and unsigned byte per parameter
139
+ length += ((totalParams + 7) >> 3) + 1 + totalParams * 2;
140
+ if (useQueryAttributes) {
141
+ // one empty length-coded name per bind parameter
142
+ length += numParams;
143
+ attrNameBuffers = new Array(numAttrs);
144
+ for (let i = 0; i < numAttrs; i++) {
145
+ const name = StringParser.encode(attrNames[i], this.encoding);
146
+ attrNameBuffers[i] = name;
147
+ length += Packet.lengthCodedNumberLength(name.length) + name.length;
148
+ }
149
+ }
150
+ for (let i = 0; i < totalParams; i++) {
151
+ if (!allParams[i].isNull) {
152
+ length += allParams[i].length;
153
+ }
154
+ }
155
+ }
156
+
157
+ const packet = new Packet(0, Buffer.allocUnsafe(length), 0, length);
109
158
  packet.offset = 4;
110
159
  packet.writeInt8(CommandCodes.STMT_EXECUTE);
111
160
  packet.writeInt32(this.id);
@@ -122,23 +171,11 @@ class Execute {
122
171
  }
123
172
 
124
173
  if (totalParams > 0) {
125
- const bindParams =
126
- numParams > 0
127
- ? this.parameters.map((v) =>
128
- toParameter(v, this.encoding, this.timezone, this.jsonAsString)
129
- )
130
- : [];
131
- const attrParams = attrNames.map((name) =>
132
- toParameter(this.attributes[name], this.encoding, this.timezone)
133
- );
134
- const allParams = bindParams.concat(attrParams);
135
-
136
- // null bitmap
137
174
  let bitmap = 0;
138
175
  let bitValue = 1;
139
- allParams.forEach((parameter) => {
140
- if (parameter.type === Types.NULL) {
141
- bitmap += bitValue;
176
+ for (let i = 0; i < totalParams; i++) {
177
+ if (allParams[i].isNull) {
178
+ bitmap |= bitValue;
142
179
  }
143
180
  bitValue *= 2;
144
181
  if (bitValue === 256) {
@@ -146,38 +183,41 @@ class Execute {
146
183
  bitmap = 0;
147
184
  bitValue = 1;
148
185
  }
149
- });
186
+ }
150
187
  if (bitValue !== 1) {
151
188
  packet.writeInt8(bitmap);
152
189
  }
153
190
 
154
191
  packet.writeInt8(1); // new-params-bound-flag
155
192
 
156
- // types (and names for attributes)
157
- for (let i = 0; i < allParams.length; i++) {
158
- packet.writeInt8(allParams[i].type);
159
- packet.writeInt8(0); // unsigned flag
193
+ for (let i = 0; i < totalParams; i++) {
194
+ const parameter = allParams[i];
195
+ packet.writeInt8(parameter.type);
196
+ packet.writeInt8(parameter.unsigned ? 0x80 : 0);
160
197
  if (useQueryAttributes) {
161
- const name = i < numParams ? '' : attrNames[i - numParams];
162
- packet.writeLengthCodedString(name, this.encoding);
198
+ if (i < numParams) {
199
+ packet.writeInt8(0); // bind parameters have an empty name
200
+ } else {
201
+ packet.writeLengthCodedBuffer(attrNameBuffers[i - numParams]);
202
+ }
163
203
  }
164
204
  }
165
205
 
166
- // values
167
- allParams.forEach((parameter) => {
168
- if (parameter.type !== Types.NULL) {
206
+ for (let i = 0; i < totalParams; i++) {
207
+ const parameter = allParams[i];
208
+ if (!parameter.isNull) {
169
209
  parameter.writer.call(packet, parameter.value);
170
210
  }
171
- });
211
+ }
172
212
  }
173
213
 
214
+ if (packet.offset !== length) {
215
+ throw new Error(
216
+ `Internal error: COM_STMT_EXECUTE serialized ${packet.offset - 4} bytes, expected ${length - 4}`
217
+ );
218
+ }
174
219
  return packet;
175
220
  }
176
-
177
- toPacket() {
178
- const p = this._serializeToBuffer(Packet.MockBuffer());
179
- return this._serializeToBuffer(Buffer.allocUnsafe(p.offset));
180
- }
181
221
  }
182
222
 
183
223
  module.exports = Execute;