mysql2 3.20.0 → 3.20.1-canary.2bdc12a4
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/commands/execute.js +5 -1
- package/lib/commands/query.js +5 -1
- package/lib/connection_config.js +1 -0
- package/lib/constants/client.js +1 -0
- package/lib/constants/cursor.js +1 -0
- package/lib/packets/encode_parameter.js +69 -0
- package/lib/packets/execute.js +68 -105
- package/lib/packets/query.js +82 -7
- package/lib/packets/resultset_header.js +1 -1
- package/package.json +1 -1
- package/typings/mysql/index.d.ts +4 -0
- package/typings/mysql/lib/protocol/sequences/Query.d.ts +7 -0
package/lib/commands/execute.js
CHANGED
|
@@ -43,11 +43,15 @@ class Execute extends Command {
|
|
|
43
43
|
this._connection = connection;
|
|
44
44
|
this.options = Object.assign({}, connection.config, this._executeOptions);
|
|
45
45
|
this._setTimeout();
|
|
46
|
+
const clientFlags =
|
|
47
|
+
connection.config.clientFlags & (connection.serverCapabilityFlags || 0);
|
|
46
48
|
const executePacket = new Packets.Execute(
|
|
47
49
|
this.statement.id,
|
|
48
50
|
this.parameters,
|
|
49
51
|
connection.config.charsetNumber,
|
|
50
|
-
connection.config.timezone
|
|
52
|
+
connection.config.timezone,
|
|
53
|
+
this._executeOptions.attributes,
|
|
54
|
+
clientFlags
|
|
51
55
|
);
|
|
52
56
|
//For reasons why this try-catch is here, please see
|
|
53
57
|
// https://github.com/sidorares/node-mysql2/pull/689
|
package/lib/commands/query.js
CHANGED
|
@@ -53,9 +53,13 @@ class Query extends Command {
|
|
|
53
53
|
this.options = Object.assign({}, connection.config, this._queryOptions);
|
|
54
54
|
this._setTimeout();
|
|
55
55
|
|
|
56
|
+
const clientFlags =
|
|
57
|
+
connection.config.clientFlags & (connection.serverCapabilityFlags || 0);
|
|
56
58
|
const cmdPacket = new Packets.Query(
|
|
57
59
|
this.sql,
|
|
58
|
-
connection.config.charsetNumber
|
|
60
|
+
connection.config.charsetNumber,
|
|
61
|
+
this._queryOptions.attributes,
|
|
62
|
+
clientFlags
|
|
59
63
|
);
|
|
60
64
|
connection.writePacket(cmdPacket.toPacket(1));
|
|
61
65
|
return Query.prototype.resultsetHeader;
|
package/lib/connection_config.js
CHANGED
package/lib/constants/client.js
CHANGED
|
@@ -31,6 +31,7 @@ exports.CONNECT_ATTRS = 0x00100000; /* permits connection attributes */
|
|
|
31
31
|
exports.PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x00200000; /* Understands length-encoded integer for auth response data in Protocol::HandshakeResponse41. */
|
|
32
32
|
exports.CAN_HANDLE_EXPIRED_PASSWORDS = 0x00400000; /* Announces support for expired password extension. */
|
|
33
33
|
exports.SESSION_TRACK = 0x00800000; /* Can set SERVER_SESSION_STATE_CHANGED in the Status Flags and send session-state change data after a OK packet. */
|
|
34
|
+
exports.CLIENT_QUERY_ATTRIBUTES = 0x08000000; /* support query attributes in COM_QUERY and COM_STMT_EXECUTE */
|
|
34
35
|
|
|
35
36
|
exports.SSL_VERIFY_SERVER_CERT = 0x40000000;
|
|
36
37
|
exports.REMEMBER_OPTIONS = 0x80000000;
|
package/lib/constants/cursor.js
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Types = require('../constants/types');
|
|
4
|
+
const Packet = require('../packets/packet');
|
|
5
|
+
|
|
6
|
+
function isJSON(value) {
|
|
7
|
+
return (
|
|
8
|
+
Array.isArray(value) ||
|
|
9
|
+
value.constructor === Object ||
|
|
10
|
+
(typeof value.toJSON === 'function' && !Buffer.isBuffer(value))
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function toParameter(value, encoding, timezone) {
|
|
15
|
+
let type = Types.VAR_STRING;
|
|
16
|
+
let length;
|
|
17
|
+
let writer = function (value) {
|
|
18
|
+
// eslint-disable-next-line no-invalid-this
|
|
19
|
+
return Packet.prototype.writeLengthCodedString.call(this, value, encoding);
|
|
20
|
+
};
|
|
21
|
+
if (value !== null) {
|
|
22
|
+
switch (typeof value) {
|
|
23
|
+
case 'undefined':
|
|
24
|
+
throw new TypeError('Bind parameters must not contain undefined');
|
|
25
|
+
|
|
26
|
+
case 'number':
|
|
27
|
+
type = Types.DOUBLE;
|
|
28
|
+
length = 8;
|
|
29
|
+
writer = Packet.prototype.writeDouble;
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
case 'boolean':
|
|
33
|
+
value = value | 0;
|
|
34
|
+
type = Types.TINY;
|
|
35
|
+
length = 1;
|
|
36
|
+
writer = Packet.prototype.writeInt8;
|
|
37
|
+
break;
|
|
38
|
+
|
|
39
|
+
case 'object':
|
|
40
|
+
if (Object.prototype.toString.call(value) === '[object Date]') {
|
|
41
|
+
type = Types.DATETIME;
|
|
42
|
+
length = 12;
|
|
43
|
+
writer = function (value) {
|
|
44
|
+
// eslint-disable-next-line no-invalid-this
|
|
45
|
+
return Packet.prototype.writeDate.call(this, value, timezone);
|
|
46
|
+
};
|
|
47
|
+
} else if (isJSON(value)) {
|
|
48
|
+
value = JSON.stringify(value);
|
|
49
|
+
type = Types.JSON;
|
|
50
|
+
} else if (Buffer.isBuffer(value)) {
|
|
51
|
+
length = Packet.lengthCodedNumberLength(value.length) + value.length;
|
|
52
|
+
writer = Packet.prototype.writeLengthCodedBuffer;
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
|
|
56
|
+
default:
|
|
57
|
+
value = value.toString();
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
value = '';
|
|
61
|
+
type = Types.NULL;
|
|
62
|
+
}
|
|
63
|
+
if (!length) {
|
|
64
|
+
length = Packet.lengthCodedStringLength(value, encoding);
|
|
65
|
+
}
|
|
66
|
+
return { value, type, length, writer };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { toParameter, isJSON };
|
package/lib/packets/execute.js
CHANGED
|
@@ -2,83 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
const CursorType = require('../constants/cursor');
|
|
4
4
|
const CommandCodes = require('../constants/commands');
|
|
5
|
+
const ClientConstants = require('../constants/client');
|
|
5
6
|
const Types = require('../constants/types');
|
|
6
7
|
const Packet = require('../packets/packet');
|
|
7
8
|
const CharsetToEncoding = require('../constants/charset_encodings.js');
|
|
8
|
-
|
|
9
|
-
function isJSON(value) {
|
|
10
|
-
return (
|
|
11
|
-
Array.isArray(value) ||
|
|
12
|
-
value.constructor === Object ||
|
|
13
|
-
(typeof value.toJSON === 'function' && !Buffer.isBuffer(value))
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Converts a value to an object describing type, String/Buffer representation and length
|
|
19
|
-
* @param {*} value
|
|
20
|
-
*/
|
|
21
|
-
function toParameter(value, encoding, timezone) {
|
|
22
|
-
let type = Types.VAR_STRING;
|
|
23
|
-
let length;
|
|
24
|
-
let writer = function (value) {
|
|
25
|
-
// eslint-disable-next-line no-invalid-this
|
|
26
|
-
return Packet.prototype.writeLengthCodedString.call(this, value, encoding);
|
|
27
|
-
};
|
|
28
|
-
if (value !== null) {
|
|
29
|
-
switch (typeof value) {
|
|
30
|
-
case 'undefined':
|
|
31
|
-
throw new TypeError('Bind parameters must not contain undefined');
|
|
32
|
-
|
|
33
|
-
case 'number':
|
|
34
|
-
type = Types.DOUBLE;
|
|
35
|
-
length = 8;
|
|
36
|
-
writer = Packet.prototype.writeDouble;
|
|
37
|
-
break;
|
|
38
|
-
|
|
39
|
-
case 'boolean':
|
|
40
|
-
value = value | 0;
|
|
41
|
-
type = Types.TINY;
|
|
42
|
-
length = 1;
|
|
43
|
-
writer = Packet.prototype.writeInt8;
|
|
44
|
-
break;
|
|
45
|
-
|
|
46
|
-
case 'object':
|
|
47
|
-
if (Object.prototype.toString.call(value) === '[object Date]') {
|
|
48
|
-
type = Types.DATETIME;
|
|
49
|
-
length = 12;
|
|
50
|
-
writer = function (value) {
|
|
51
|
-
// eslint-disable-next-line no-invalid-this
|
|
52
|
-
return Packet.prototype.writeDate.call(this, value, timezone);
|
|
53
|
-
};
|
|
54
|
-
} else if (isJSON(value)) {
|
|
55
|
-
value = JSON.stringify(value);
|
|
56
|
-
type = Types.JSON;
|
|
57
|
-
} else if (Buffer.isBuffer(value)) {
|
|
58
|
-
length = Packet.lengthCodedNumberLength(value.length) + value.length;
|
|
59
|
-
writer = Packet.prototype.writeLengthCodedBuffer;
|
|
60
|
-
}
|
|
61
|
-
break;
|
|
62
|
-
|
|
63
|
-
default:
|
|
64
|
-
value = value.toString();
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
value = '';
|
|
68
|
-
type = Types.NULL;
|
|
69
|
-
}
|
|
70
|
-
if (!length) {
|
|
71
|
-
length = Packet.lengthCodedStringLength(value, encoding);
|
|
72
|
-
}
|
|
73
|
-
return { value, type, length, writer };
|
|
74
|
-
}
|
|
9
|
+
const { toParameter } = require('./encode_parameter.js');
|
|
75
10
|
|
|
76
11
|
class Execute {
|
|
77
|
-
constructor(
|
|
12
|
+
constructor(
|
|
13
|
+
id,
|
|
14
|
+
parameters,
|
|
15
|
+
charsetNumber,
|
|
16
|
+
timezone,
|
|
17
|
+
attributes,
|
|
18
|
+
clientFlags
|
|
19
|
+
) {
|
|
78
20
|
this.id = id;
|
|
79
21
|
this.parameters = parameters;
|
|
80
22
|
this.encoding = CharsetToEncoding[charsetNumber];
|
|
81
23
|
this.timezone = timezone;
|
|
24
|
+
this.attributes = attributes;
|
|
25
|
+
this.clientFlags = clientFlags || 0;
|
|
82
26
|
}
|
|
83
27
|
|
|
84
28
|
static fromPacket(packet, encoding) {
|
|
@@ -145,39 +89,48 @@ class Execute {
|
|
|
145
89
|
return { stmtId, flags, iterationCount, values };
|
|
146
90
|
}
|
|
147
91
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
length += Math.floor((this.parameters.length + 7) / 8);
|
|
160
|
-
length += 1; // new-params-bound-flag
|
|
161
|
-
length += 2 * this.parameters.length; // type byte for each parameter if new-params-bound-flag is set
|
|
162
|
-
parameters = this.parameters.map((value) =>
|
|
163
|
-
toParameter(value, this.encoding, this.timezone)
|
|
164
|
-
);
|
|
165
|
-
length += parameters.reduce(
|
|
166
|
-
(accumulator, parameter) => accumulator + parameter.length,
|
|
167
|
-
0
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
const buffer = Buffer.allocUnsafe(length);
|
|
171
|
-
const packet = new Packet(0, buffer, 0, length);
|
|
92
|
+
_serializeToBuffer(buffer) {
|
|
93
|
+
const useQueryAttributes =
|
|
94
|
+
this.clientFlags & ClientConstants.CLIENT_QUERY_ATTRIBUTES;
|
|
95
|
+
|
|
96
|
+
const attrNames =
|
|
97
|
+
useQueryAttributes && this.attributes ? Object.keys(this.attributes) : [];
|
|
98
|
+
const numParams = this.parameters ? this.parameters.length : 0;
|
|
99
|
+
const numAttrs = attrNames.length;
|
|
100
|
+
const totalParams = numParams + numAttrs;
|
|
101
|
+
|
|
102
|
+
const packet = new Packet(0, buffer, 0, buffer.length);
|
|
172
103
|
packet.offset = 4;
|
|
173
104
|
packet.writeInt8(CommandCodes.STMT_EXECUTE);
|
|
174
105
|
packet.writeInt32(this.id);
|
|
175
|
-
|
|
106
|
+
|
|
107
|
+
let cursorFlags = CursorType.NO_CURSOR;
|
|
108
|
+
if (useQueryAttributes) {
|
|
109
|
+
cursorFlags |= CursorType.PARAMETER_COUNT_AVAILABLE;
|
|
110
|
+
}
|
|
111
|
+
packet.writeInt8(cursorFlags);
|
|
176
112
|
packet.writeInt32(1); // iteration-count, always 1
|
|
177
|
-
|
|
113
|
+
|
|
114
|
+
if (useQueryAttributes) {
|
|
115
|
+
packet.writeLengthCodedNumber(totalParams);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (totalParams > 0) {
|
|
119
|
+
const bindParams =
|
|
120
|
+
numParams > 0
|
|
121
|
+
? this.parameters.map((v) =>
|
|
122
|
+
toParameter(v, this.encoding, this.timezone)
|
|
123
|
+
)
|
|
124
|
+
: [];
|
|
125
|
+
const attrParams = attrNames.map((name) =>
|
|
126
|
+
toParameter(this.attributes[name], this.encoding, this.timezone)
|
|
127
|
+
);
|
|
128
|
+
const allParams = bindParams.concat(attrParams);
|
|
129
|
+
|
|
130
|
+
// null bitmap
|
|
178
131
|
let bitmap = 0;
|
|
179
132
|
let bitValue = 1;
|
|
180
|
-
|
|
133
|
+
allParams.forEach((parameter) => {
|
|
181
134
|
if (parameter.type === Types.NULL) {
|
|
182
135
|
bitmap += bitValue;
|
|
183
136
|
}
|
|
@@ -191,24 +144,34 @@ class Execute {
|
|
|
191
144
|
if (bitValue !== 1) {
|
|
192
145
|
packet.writeInt8(bitmap);
|
|
193
146
|
}
|
|
194
|
-
|
|
195
|
-
// afaik, if set n*2 bytes with type of parameter are sent before parameters
|
|
196
|
-
// if not, previous execution types are used (TODO prooflink)
|
|
147
|
+
|
|
197
148
|
packet.writeInt8(1); // new-params-bound-flag
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
packet.writeInt8(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
149
|
+
|
|
150
|
+
// types (and names for attributes)
|
|
151
|
+
for (let i = 0; i < allParams.length; i++) {
|
|
152
|
+
packet.writeInt8(allParams[i].type);
|
|
153
|
+
packet.writeInt8(0); // unsigned flag
|
|
154
|
+
if (useQueryAttributes) {
|
|
155
|
+
const name = i < numParams ? '' : attrNames[i - numParams];
|
|
156
|
+
packet.writeLengthCodedString(name, this.encoding);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// values
|
|
161
|
+
allParams.forEach((parameter) => {
|
|
205
162
|
if (parameter.type !== Types.NULL) {
|
|
206
163
|
parameter.writer.call(packet, parameter.value);
|
|
207
164
|
}
|
|
208
165
|
});
|
|
209
166
|
}
|
|
167
|
+
|
|
210
168
|
return packet;
|
|
211
169
|
}
|
|
170
|
+
|
|
171
|
+
toPacket() {
|
|
172
|
+
const p = this._serializeToBuffer(Packet.MockBuffer());
|
|
173
|
+
return this._serializeToBuffer(Buffer.allocUnsafe(p.offset));
|
|
174
|
+
}
|
|
212
175
|
}
|
|
213
176
|
|
|
214
177
|
module.exports = Execute;
|
package/lib/packets/query.js
CHANGED
|
@@ -4,24 +4,99 @@ const Packet = require('../packets/packet.js');
|
|
|
4
4
|
const CommandCode = require('../constants/commands.js');
|
|
5
5
|
const StringParser = require('../parsers/string.js');
|
|
6
6
|
const CharsetToEncoding = require('../constants/charset_encodings.js');
|
|
7
|
+
const ClientConstants = require('../constants/client.js');
|
|
8
|
+
const Types = require('../constants/types.js');
|
|
9
|
+
const { toParameter } = require('./encode_parameter.js');
|
|
7
10
|
|
|
8
11
|
class Query {
|
|
9
|
-
constructor(sql, charsetNumber) {
|
|
12
|
+
constructor(sql, charsetNumber, attributes, clientFlags) {
|
|
10
13
|
this.query = sql;
|
|
11
14
|
this.charsetNumber = charsetNumber;
|
|
12
15
|
this.encoding = CharsetToEncoding[charsetNumber];
|
|
16
|
+
this.attributes = attributes;
|
|
17
|
+
this.clientFlags = clientFlags || 0;
|
|
13
18
|
}
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
const packet = new Packet(0, buffer, 0, length);
|
|
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);
|
|
20
25
|
packet.offset = 4;
|
|
21
26
|
packet.writeInt8(CommandCode.QUERY);
|
|
22
|
-
|
|
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);
|
|
23
78
|
return packet;
|
|
24
79
|
}
|
|
80
|
+
|
|
81
|
+
toPacket() {
|
|
82
|
+
const useQueryAttributes =
|
|
83
|
+
this.clientFlags & ClientConstants.CLIENT_QUERY_ATTRIBUTES;
|
|
84
|
+
|
|
85
|
+
if (!useQueryAttributes) {
|
|
86
|
+
const buf = StringParser.encode(this.query, this.encoding);
|
|
87
|
+
const length = 5 + buf.length;
|
|
88
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
89
|
+
const packet = new Packet(0, buffer, 0, length);
|
|
90
|
+
packet.offset = 4;
|
|
91
|
+
packet.writeInt8(CommandCode.QUERY);
|
|
92
|
+
packet.writeBuffer(buf);
|
|
93
|
+
return packet;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// dry run to calculate required buffer length
|
|
97
|
+
const p = this.serializeToBuffer(Packet.MockBuffer());
|
|
98
|
+
return this.serializeToBuffer(Buffer.allocUnsafe(p.offset));
|
|
99
|
+
}
|
|
25
100
|
}
|
|
26
101
|
|
|
27
102
|
module.exports = Query;
|
|
@@ -39,7 +39,7 @@ class ResultSetHeader {
|
|
|
39
39
|
if (isSet('SESSION_TRACK') && packet.offset < packet.end) {
|
|
40
40
|
this.info = packet.readLengthCodedString(encoding);
|
|
41
41
|
|
|
42
|
-
if (this.serverStatus
|
|
42
|
+
if (this.serverStatus & ServerSatusFlags.SERVER_SESSION_STATE_CHANGED) {
|
|
43
43
|
// session change info record - see
|
|
44
44
|
// https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html#cs-sect-packet-ok-sessioninfo
|
|
45
45
|
let len =
|
package/package.json
CHANGED
package/typings/mysql/index.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
Query as BaseQuery,
|
|
9
9
|
QueryOptions,
|
|
10
10
|
QueryError,
|
|
11
|
+
ExecuteValues,
|
|
12
|
+
QueryValues,
|
|
11
13
|
} from './lib/protocol/sequences/Query.js';
|
|
12
14
|
import {
|
|
13
15
|
PoolCluster as BasePoolCluster,
|
|
@@ -35,6 +37,8 @@ export {
|
|
|
35
37
|
PoolNamespace,
|
|
36
38
|
QueryOptions,
|
|
37
39
|
QueryError,
|
|
40
|
+
ExecuteValues,
|
|
41
|
+
QueryValues,
|
|
38
42
|
PrepareStatementInfo,
|
|
39
43
|
};
|
|
40
44
|
|
|
@@ -43,6 +43,13 @@ export interface QueryOptions {
|
|
|
43
43
|
*/
|
|
44
44
|
values?: QueryValues;
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Query attributes sent alongside the query (MySQL 8.0.25+).
|
|
48
|
+
* Requires the `component_query_attributes` server component to be read via
|
|
49
|
+
* `mysql_query_attribute_string()`.
|
|
50
|
+
*/
|
|
51
|
+
attributes?: Record<string, string | number | boolean | null | Buffer | Date>;
|
|
52
|
+
|
|
46
53
|
/**
|
|
47
54
|
* This overrides the namedPlaceholders option set at the connection level.
|
|
48
55
|
*/
|