mysql2 3.23.5-canary.c86fe5a → 3.24.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/lib/packets/encode_parameter.js +9 -5
- package/lib/packets/execute.js +70 -38
- package/lib/packets/packet.js +8 -0
- package/lib/packets/query.js +75 -65
- package/lib/packets/typed_parameter.js +20 -20
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const Types = require('../constants/types');
|
|
4
4
|
const Packet = require('../packets/packet');
|
|
5
|
+
const StringParser = require('../parsers/string.js');
|
|
5
6
|
const {
|
|
6
7
|
TypedParameter,
|
|
7
8
|
encodeTypedParameter,
|
|
@@ -33,9 +34,7 @@ function toParameter(value, encoding, timezone, jsonAsString, hint) {
|
|
|
33
34
|
}
|
|
34
35
|
let type = Types.VAR_STRING;
|
|
35
36
|
let length;
|
|
36
|
-
let writer =
|
|
37
|
-
return Packet.prototype.writeLengthCodedString.call(this, value, encoding);
|
|
38
|
-
};
|
|
37
|
+
let writer = Packet.prototype.writeLengthCodedBuffer;
|
|
39
38
|
if (value !== null) {
|
|
40
39
|
switch (typeof value) {
|
|
41
40
|
case 'undefined':
|
|
@@ -86,9 +85,12 @@ function toParameter(value, encoding, timezone, jsonAsString, hint) {
|
|
|
86
85
|
} else {
|
|
87
86
|
value = '';
|
|
88
87
|
type = Types.NULL;
|
|
88
|
+
length = 0;
|
|
89
|
+
writer = writeNothing;
|
|
89
90
|
}
|
|
90
|
-
if (
|
|
91
|
-
|
|
91
|
+
if (length === undefined) {
|
|
92
|
+
value = StringParser.encode(value, encoding);
|
|
93
|
+
length = Packet.lengthCodedNumberLength(value.length) + value.length;
|
|
92
94
|
}
|
|
93
95
|
return {
|
|
94
96
|
value,
|
|
@@ -100,4 +102,6 @@ function toParameter(value, encoding, timezone, jsonAsString, hint) {
|
|
|
100
102
|
};
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
function writeNothing() {}
|
|
106
|
+
|
|
103
107
|
module.exports = { toParameter, isJSON };
|
package/lib/packets/execute.js
CHANGED
|
@@ -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
|
|
|
@@ -97,7 +98,7 @@ class Execute {
|
|
|
97
98
|
return { stmtId, flags, iterationCount, values };
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
|
|
101
|
+
toPacket() {
|
|
101
102
|
const useQueryAttributes =
|
|
102
103
|
this.clientFlags & ClientConstants.CLIENT_QUERY_ATTRIBUTES;
|
|
103
104
|
|
|
@@ -107,7 +108,53 @@ class Execute {
|
|
|
107
108
|
const numAttrs = attrNames.length;
|
|
108
109
|
const totalParams = numParams + numAttrs;
|
|
109
110
|
|
|
110
|
-
|
|
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);
|
|
111
158
|
packet.offset = 4;
|
|
112
159
|
packet.writeInt8(CommandCodes.STMT_EXECUTE);
|
|
113
160
|
packet.writeInt32(this.id);
|
|
@@ -124,29 +171,11 @@ class Execute {
|
|
|
124
171
|
}
|
|
125
172
|
|
|
126
173
|
if (totalParams > 0) {
|
|
127
|
-
const bindParams =
|
|
128
|
-
numParams > 0
|
|
129
|
-
? this.parameters.map((v, i) =>
|
|
130
|
-
toParameter(
|
|
131
|
-
v,
|
|
132
|
-
this.encoding,
|
|
133
|
-
this.timezone,
|
|
134
|
-
this.jsonAsString,
|
|
135
|
-
this.parameterDefinitions[i]
|
|
136
|
-
)
|
|
137
|
-
)
|
|
138
|
-
: [];
|
|
139
|
-
const attrParams = attrNames.map((name) =>
|
|
140
|
-
toParameter(this.attributes[name], this.encoding, this.timezone)
|
|
141
|
-
);
|
|
142
|
-
const allParams = bindParams.concat(attrParams);
|
|
143
|
-
|
|
144
|
-
// null bitmap
|
|
145
174
|
let bitmap = 0;
|
|
146
175
|
let bitValue = 1;
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
bitmap
|
|
176
|
+
for (let i = 0; i < totalParams; i++) {
|
|
177
|
+
if (allParams[i].isNull) {
|
|
178
|
+
bitmap |= bitValue;
|
|
150
179
|
}
|
|
151
180
|
bitValue *= 2;
|
|
152
181
|
if (bitValue === 256) {
|
|
@@ -154,38 +183,41 @@ class Execute {
|
|
|
154
183
|
bitmap = 0;
|
|
155
184
|
bitValue = 1;
|
|
156
185
|
}
|
|
157
|
-
}
|
|
186
|
+
}
|
|
158
187
|
if (bitValue !== 1) {
|
|
159
188
|
packet.writeInt8(bitmap);
|
|
160
189
|
}
|
|
161
190
|
|
|
162
191
|
packet.writeInt8(1); // new-params-bound-flag
|
|
163
192
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
packet.writeInt8(
|
|
167
|
-
packet.writeInt8(
|
|
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);
|
|
168
197
|
if (useQueryAttributes) {
|
|
169
|
-
|
|
170
|
-
|
|
198
|
+
if (i < numParams) {
|
|
199
|
+
packet.writeInt8(0); // bind parameters have an empty name
|
|
200
|
+
} else {
|
|
201
|
+
packet.writeLengthCodedBuffer(attrNameBuffers[i - numParams]);
|
|
202
|
+
}
|
|
171
203
|
}
|
|
172
204
|
}
|
|
173
205
|
|
|
174
|
-
|
|
175
|
-
|
|
206
|
+
for (let i = 0; i < totalParams; i++) {
|
|
207
|
+
const parameter = allParams[i];
|
|
176
208
|
if (!parameter.isNull) {
|
|
177
209
|
parameter.writer.call(packet, parameter.value);
|
|
178
210
|
}
|
|
179
|
-
}
|
|
211
|
+
}
|
|
180
212
|
}
|
|
181
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
|
+
}
|
|
182
219
|
return packet;
|
|
183
220
|
}
|
|
184
|
-
|
|
185
|
-
toPacket() {
|
|
186
|
-
const p = this._serializeToBuffer(Packet.MockBuffer());
|
|
187
|
-
return this._serializeToBuffer(Buffer.allocUnsafe(p.offset));
|
|
188
|
-
}
|
|
189
221
|
}
|
|
190
222
|
|
|
191
223
|
module.exports = Execute;
|
package/lib/packets/packet.js
CHANGED
|
@@ -965,6 +965,14 @@ class Packet {
|
|
|
965
965
|
this.offset += bytes;
|
|
966
966
|
}
|
|
967
967
|
|
|
968
|
+
// must match writeTime's choice of encoding byte for byte
|
|
969
|
+
static timeLength({ days, hours, minutes, seconds, microseconds }) {
|
|
970
|
+
if (!days && !hours && !minutes && !seconds && !microseconds) {
|
|
971
|
+
return 1;
|
|
972
|
+
}
|
|
973
|
+
return microseconds ? 13 : 9;
|
|
974
|
+
}
|
|
975
|
+
|
|
968
976
|
writeTime({ negative, days, hours, minutes, seconds, microseconds }) {
|
|
969
977
|
if (!days && !hours && !minutes && !seconds && !microseconds) {
|
|
970
978
|
this.writeInt8(0);
|
package/lib/packets/query.js
CHANGED
|
@@ -5,7 +5,6 @@ const CommandCode = require('../constants/commands.js');
|
|
|
5
5
|
const StringParser = require('../parsers/string.js');
|
|
6
6
|
const CharsetToEncoding = require('../constants/charset_encodings.js');
|
|
7
7
|
const ClientConstants = require('../constants/client.js');
|
|
8
|
-
const Types = require('../constants/types.js');
|
|
9
8
|
const { toParameter } = require('./encode_parameter.js');
|
|
10
9
|
|
|
11
10
|
class Query {
|
|
@@ -17,67 +16,6 @@ class Query {
|
|
|
17
16
|
this.clientFlags = clientFlags || 0;
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
serializeToBuffer(buffer) {
|
|
21
|
-
const useQueryAttributes =
|
|
22
|
-
this.clientFlags & ClientConstants.CLIENT_QUERY_ATTRIBUTES;
|
|
23
|
-
const sqlBuf = StringParser.encode(this.query, this.encoding);
|
|
24
|
-
const packet = new Packet(0, buffer, 0, buffer.length);
|
|
25
|
-
packet.offset = 4;
|
|
26
|
-
packet.writeInt8(CommandCode.QUERY);
|
|
27
|
-
|
|
28
|
-
if (useQueryAttributes) {
|
|
29
|
-
const attrs = this.attributes;
|
|
30
|
-
const names = attrs ? Object.keys(attrs) : [];
|
|
31
|
-
const paramCount = names.length;
|
|
32
|
-
|
|
33
|
-
packet.writeLengthCodedNumber(paramCount);
|
|
34
|
-
packet.writeLengthCodedNumber(1); // parameter_set_count, always 1
|
|
35
|
-
|
|
36
|
-
if (paramCount > 0) {
|
|
37
|
-
const parameters = names.map((name) =>
|
|
38
|
-
toParameter(attrs[name], this.encoding, 'local')
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
// null bitmap
|
|
42
|
-
let bitmap = 0;
|
|
43
|
-
let bitValue = 1;
|
|
44
|
-
parameters.forEach((parameter) => {
|
|
45
|
-
if (parameter.type === Types.NULL) {
|
|
46
|
-
bitmap += bitValue;
|
|
47
|
-
}
|
|
48
|
-
bitValue *= 2;
|
|
49
|
-
if (bitValue === 256) {
|
|
50
|
-
packet.writeInt8(bitmap);
|
|
51
|
-
bitmap = 0;
|
|
52
|
-
bitValue = 1;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
if (bitValue !== 1) {
|
|
56
|
-
packet.writeInt8(bitmap);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
packet.writeInt8(1); // new_params_bind_flag
|
|
60
|
-
|
|
61
|
-
// types and names
|
|
62
|
-
for (let i = 0; i < paramCount; i++) {
|
|
63
|
-
packet.writeInt8(parameters[i].type);
|
|
64
|
-
packet.writeInt8(0); // unsigned flag
|
|
65
|
-
packet.writeLengthCodedString(names[i], this.encoding);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// values
|
|
69
|
-
parameters.forEach((parameter) => {
|
|
70
|
-
if (parameter.type !== Types.NULL) {
|
|
71
|
-
parameter.writer.call(packet, parameter.value);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
packet.writeBuffer(sqlBuf);
|
|
78
|
-
return packet;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
19
|
toPacket() {
|
|
82
20
|
const useQueryAttributes =
|
|
83
21
|
this.clientFlags & ClientConstants.CLIENT_QUERY_ATTRIBUTES;
|
|
@@ -119,9 +57,81 @@ class Query {
|
|
|
119
57
|
return packet;
|
|
120
58
|
}
|
|
121
59
|
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
60
|
+
const names = Object.keys(this.attributes);
|
|
61
|
+
const parameters = new Array(attributeCount);
|
|
62
|
+
const nameBuffers = new Array(attributeCount);
|
|
63
|
+
|
|
64
|
+
// packet header, command, parameter count, parameter_set_count (always
|
|
65
|
+
// the single-byte form), null bitmap, new_params_bind_flag, type and
|
|
66
|
+
// unsigned byte per parameter
|
|
67
|
+
let length =
|
|
68
|
+
5 +
|
|
69
|
+
Packet.lengthCodedNumberLength(attributeCount) +
|
|
70
|
+
1 +
|
|
71
|
+
((attributeCount + 7) >> 3) +
|
|
72
|
+
1 +
|
|
73
|
+
attributeCount * 2;
|
|
74
|
+
for (let i = 0; i < attributeCount; i++) {
|
|
75
|
+
parameters[i] = toParameter(
|
|
76
|
+
this.attributes[names[i]],
|
|
77
|
+
this.encoding,
|
|
78
|
+
'local'
|
|
79
|
+
);
|
|
80
|
+
const name = StringParser.encode(names[i], this.encoding);
|
|
81
|
+
nameBuffers[i] = name;
|
|
82
|
+
length += Packet.lengthCodedNumberLength(name.length) + name.length;
|
|
83
|
+
if (!parameters[i].isNull) {
|
|
84
|
+
length += parameters[i].length;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const sqlBuffer = StringParser.encode(this.query, this.encoding);
|
|
88
|
+
length += sqlBuffer.length;
|
|
89
|
+
|
|
90
|
+
const packet = new Packet(0, Buffer.allocUnsafe(length), 0, length);
|
|
91
|
+
packet.offset = 4;
|
|
92
|
+
packet.writeInt8(CommandCode.QUERY);
|
|
93
|
+
packet.writeLengthCodedNumber(attributeCount);
|
|
94
|
+
packet.writeLengthCodedNumber(1); // parameter_set_count, always 1
|
|
95
|
+
|
|
96
|
+
let bitmap = 0;
|
|
97
|
+
let bitValue = 1;
|
|
98
|
+
for (let i = 0; i < attributeCount; i++) {
|
|
99
|
+
if (parameters[i].isNull) {
|
|
100
|
+
bitmap |= bitValue;
|
|
101
|
+
}
|
|
102
|
+
bitValue *= 2;
|
|
103
|
+
if (bitValue === 256) {
|
|
104
|
+
packet.writeInt8(bitmap);
|
|
105
|
+
bitmap = 0;
|
|
106
|
+
bitValue = 1;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (bitValue !== 1) {
|
|
110
|
+
packet.writeInt8(bitmap);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
packet.writeInt8(1); // new_params_bind_flag
|
|
114
|
+
|
|
115
|
+
for (let i = 0; i < attributeCount; i++) {
|
|
116
|
+
packet.writeInt8(parameters[i].type);
|
|
117
|
+
packet.writeInt8(parameters[i].unsigned ? 0x80 : 0);
|
|
118
|
+
packet.writeLengthCodedBuffer(nameBuffers[i]);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < attributeCount; i++) {
|
|
122
|
+
if (!parameters[i].isNull) {
|
|
123
|
+
parameters[i].writer.call(packet, parameters[i].value);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
packet.writeBuffer(sqlBuffer);
|
|
128
|
+
|
|
129
|
+
if (packet.offset !== length) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
`Internal error: COM_QUERY serialized ${packet.offset - 4} bytes, expected ${length - 4}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return packet;
|
|
125
135
|
}
|
|
126
136
|
}
|
|
127
137
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const Types = require('../constants/types.js');
|
|
4
4
|
const Packet = require('./packet.js');
|
|
5
|
+
const StringParser = require('../parsers/string.js');
|
|
5
6
|
|
|
6
7
|
const INTEGER_BYTES = {
|
|
7
8
|
[Types.TINY]: 1,
|
|
@@ -223,31 +224,30 @@ function toTimeParts(value) {
|
|
|
223
224
|
}
|
|
224
225
|
|
|
225
226
|
function timeEncoder() {
|
|
226
|
-
return (value) =>
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
227
|
+
return (value) => {
|
|
228
|
+
const parts = toTimeParts(value);
|
|
229
|
+
return {
|
|
230
|
+
value: parts,
|
|
231
|
+
length: Packet.timeLength(parts),
|
|
232
|
+
writer(v) {
|
|
233
|
+
this.writeTime(v);
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
};
|
|
233
237
|
}
|
|
234
238
|
|
|
235
239
|
function lengthCodedEncoder(encoding) {
|
|
236
240
|
return (value) => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
const str = typeof value === 'string' ? value : String(value);
|
|
241
|
+
const buffer = Buffer.isBuffer(value)
|
|
242
|
+
? value
|
|
243
|
+
: StringParser.encode(
|
|
244
|
+
typeof value === 'string' ? value : String(value),
|
|
245
|
+
encoding
|
|
246
|
+
);
|
|
245
247
|
return {
|
|
246
|
-
value:
|
|
247
|
-
length: Packet.
|
|
248
|
-
writer
|
|
249
|
-
Packet.prototype.writeLengthCodedString.call(this, v, encoding);
|
|
250
|
-
},
|
|
248
|
+
value: buffer,
|
|
249
|
+
length: Packet.lengthCodedNumberLength(buffer.length) + buffer.length,
|
|
250
|
+
writer: Packet.prototype.writeLengthCodedBuffer,
|
|
251
251
|
};
|
|
252
252
|
};
|
|
253
253
|
}
|
package/package.json
CHANGED