Skip to content

Commit b9b41cc

Browse files
committed
Merge branch 'master' into claude/library-performance-analysis-d4d3b6
Conflicts: lib/packets/packet.js - kept master's ZERO_DATE prefix detection for binary zero dates (#4491) but return a fresh new Date(NaN) instead of the shared INVALID_DATE singleton, which this branch removed (Date is mutable) - dropped the now-unused INVALID_DATE constant
2 parents 2c7945d + 8ec20f1 commit b9b41cc

22 files changed

Lines changed: 1605 additions & 56 deletions

‎index.js‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ exports.__defineGetter__(
6060

6161
exports.__defineGetter__('Types', () => require('./lib/constants/types.js'));
6262

63+
exports.__defineGetter__(
64+
'TypedParameter',
65+
() => require('./lib/packets/typed_parameter.js').types
66+
);
67+
6368
exports.__defineGetter__('Charsets', () =>
6469
require('./lib/constants/charsets.js')
6570
);

‎lib/commands/execute.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class Execute extends Command {
5656
connection.config.timezone,
5757
this._executeOptions.attributes,
5858
clientFlags,
59-
connection._isMariaDB
59+
connection._isMariaDB,
60+
this.statement.parameters
6061
);
6162
//For reasons why this try-catch is here, please see
6263
// https://github.com/sidorares/node-mysql2/pull/689

‎lib/constants/types.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module.exports = {
1818
0x0e: 'NEWDATE', // aka ?
1919
0x0f: 'VARCHAR', // aka VARCHAR (?)
2020
0x10: 'BIT', // aka BIT, 1-8 byte
21+
0xf2: 'VECTOR',
2122
0xf5: 'JSON',
2223
0xf6: 'NEWDECIMAL', // aka DECIMAL
2324
0xf7: 'ENUM', // aka ENUM

‎lib/packets/encode_parameter.js‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
const Types = require('../constants/types');
44
const Packet = require('../packets/packet');
5+
const {
6+
TypedParameter,
7+
encodeTypedParameter,
8+
integerHint,
9+
} = require('./typed_parameter.js');
10+
const FieldFlags = require('../constants/field_flags.js');
511

612
function isJSON(value) {
713
return (
@@ -11,7 +17,20 @@ function isJSON(value) {
1117
);
1218
}
1319

14-
function toParameter(value, encoding, timezone, jsonAsString) {
20+
function toParameter(value, encoding, timezone, jsonAsString, hint) {
21+
if (value instanceof TypedParameter) {
22+
return encodeTypedParameter(value, encoding, timezone, jsonAsString);
23+
}
24+
if (hint) {
25+
const hinted = integerHint(
26+
value,
27+
hint.columnType,
28+
Boolean(hint.flags & FieldFlags.UNSIGNED)
29+
);
30+
if (hinted) {
31+
return encodeTypedParameter(hinted, encoding, timezone, jsonAsString);
32+
}
33+
}
1534
let type = Types.VAR_STRING;
1635
let length;
1736
let writer = function (value) {
@@ -71,7 +90,14 @@ function toParameter(value, encoding, timezone, jsonAsString) {
7190
if (!length) {
7291
length = Packet.lengthCodedStringLength(value, encoding);
7392
}
74-
return { value, type, length, writer };
93+
return {
94+
value,
95+
type,
96+
length,
97+
writer,
98+
unsigned: false,
99+
isNull: type === Types.NULL,
100+
};
75101
}
76102

77103
module.exports = { toParameter, isJSON };

‎lib/packets/execute.js‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class Execute {
1616
timezone,
1717
attributes,
1818
clientFlags,
19-
jsonAsString
19+
jsonAsString,
20+
parameterDefinitions
2021
) {
2122
this.id = id;
2223
this.parameters = parameters;
@@ -25,6 +26,7 @@ class Execute {
2526
this.attributes = attributes;
2627
this.clientFlags = clientFlags || 0;
2728
this.jsonAsString = jsonAsString || false;
29+
this.parameterDefinitions = parameterDefinitions || [];
2830
}
2931

3032
static fromPacket(packet, encoding) {
@@ -124,8 +126,14 @@ class Execute {
124126
if (totalParams > 0) {
125127
const bindParams =
126128
numParams > 0
127-
? this.parameters.map((v) =>
128-
toParameter(v, this.encoding, this.timezone, this.jsonAsString)
129+
? this.parameters.map((v, i) =>
130+
toParameter(
131+
v,
132+
this.encoding,
133+
this.timezone,
134+
this.jsonAsString,
135+
this.parameterDefinitions[i]
136+
)
129137
)
130138
: [];
131139
const attrParams = attrNames.map((name) =>
@@ -137,7 +145,7 @@ class Execute {
137145
let bitmap = 0;
138146
let bitValue = 1;
139147
allParams.forEach((parameter) => {
140-
if (parameter.type === Types.NULL) {
148+
if (parameter.isNull) {
141149
bitmap += bitValue;
142150
}
143151
bitValue *= 2;
@@ -156,7 +164,7 @@ class Execute {
156164
// types (and names for attributes)
157165
for (let i = 0; i < allParams.length; i++) {
158166
packet.writeInt8(allParams[i].type);
159-
packet.writeInt8(0); // unsigned flag
167+
packet.writeInt8(allParams[i].unsigned ? 0x80 : 0);
160168
if (useQueryAttributes) {
161169
const name = i < numParams ? '' : attrNames[i - numParams];
162170
packet.writeLengthCodedString(name, this.encoding);
@@ -165,7 +173,7 @@ class Execute {
165173

166174
// values
167175
allParams.forEach((parameter) => {
168-
if (parameter.type !== Types.NULL) {
176+
if (!parameter.isNull) {
169177
parameter.writer.call(packet, parameter.value);
170178
}
171179
});

‎lib/packets/packet.js‎

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const NativeBuffer = require('buffer').Buffer;
1010
const Long = require('long');
1111
const StringParser = require('../parsers/string.js');
1212
const Types = require('../constants/types.js');
13+
const ZERO_DATE = '0000-00-00';
1314

1415
// this is nearly duplicate of previous function so generated code is not slower
1516
// due to "if (dateStrings)" branching
@@ -337,7 +338,9 @@ class Packet {
337338
return new Date(y, m - 1, d, H, M, S, ms);
338339
}
339340
let str = this.readDateTimeString(6, 'T', null);
340-
if (!str) {
341+
if (str.startsWith(ZERO_DATE)) {
342+
// fresh instance: Date is mutable, a shared invalid-date singleton
343+
// could be corrupted by callers (see the parseDateTime tests)
341344
return new Date(NaN);
342345
}
343346
if (str.length === 10) {
@@ -355,7 +358,7 @@ class Packet {
355358
let M = 0;
356359
let S = 0;
357360
let ms = 0;
358-
let str;
361+
let str = ZERO_DATE;
359362
if (length > 3) {
360363
y = this.readInt16();
361364
m = this.readInt8();
@@ -948,6 +951,36 @@ class Packet {
948951
this.offset += 8;
949952
}
950953

954+
writeFloat(n) {
955+
this.buffer.writeFloatLE(n, this.offset);
956+
this.offset += 4;
957+
}
958+
959+
writeUIntLE(n, bytes) {
960+
if (bytes === 8) {
961+
this.buffer.writeBigUInt64LE(n, this.offset);
962+
} else {
963+
this.buffer.writeUIntLE(Number(n), this.offset, bytes);
964+
}
965+
this.offset += bytes;
966+
}
967+
968+
writeTime({ negative, days, hours, minutes, seconds, microseconds }) {
969+
if (!days && !hours && !minutes && !seconds && !microseconds) {
970+
this.writeInt8(0);
971+
return;
972+
}
973+
this.writeInt8(microseconds ? 12 : 8);
974+
this.writeInt8(negative ? 1 : 0);
975+
this.writeInt32(days);
976+
this.writeInt8(hours);
977+
this.writeInt8(minutes);
978+
this.writeInt8(seconds);
979+
if (microseconds) {
980+
this.writeInt32(microseconds);
981+
}
982+
}
983+
951984
writeBuffer(b) {
952985
b.copy(this.buffer, this.offset);
953986
this.offset += b.length;

0 commit comments

Comments
 (0)