@tachybase/module-multi-app 1.5.1 → 1.6.1
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/dist/externalVersion.js +5 -5
- package/dist/node_modules/mariadb/callback.js +43 -8
- package/dist/node_modules/mariadb/check-node.js +30 -0
- package/dist/node_modules/mariadb/lib/cluster-callback.js +84 -0
- package/dist/node_modules/mariadb/lib/cluster.js +446 -0
- package/dist/node_modules/mariadb/lib/cmd/batch-bulk.js +576 -177
- package/dist/node_modules/mariadb/lib/cmd/change-user.js +54 -44
- package/dist/node_modules/mariadb/lib/cmd/class/ok-packet.js +3 -2
- package/dist/node_modules/mariadb/lib/cmd/class/prepare-cache-wrapper.js +46 -0
- package/dist/node_modules/mariadb/lib/cmd/class/prepare-result-packet.js +141 -0
- package/dist/node_modules/mariadb/lib/cmd/class/prepare-wrapper.js +70 -0
- package/dist/node_modules/mariadb/lib/cmd/close-prepare.js +38 -0
- package/dist/node_modules/mariadb/lib/cmd/column-definition.js +145 -47
- package/dist/node_modules/mariadb/lib/cmd/command.js +41 -75
- package/dist/node_modules/mariadb/lib/cmd/decoder/binary-decoder.js +282 -0
- package/dist/node_modules/mariadb/lib/cmd/decoder/text-decoder.js +210 -0
- package/dist/node_modules/mariadb/lib/cmd/{common-binary-cmd.js → encoder/binary-encoder.js} +34 -77
- package/dist/node_modules/mariadb/lib/cmd/encoder/text-encoder.js +311 -0
- package/dist/node_modules/mariadb/lib/cmd/execute-stream.js +61 -0
- package/dist/node_modules/mariadb/lib/cmd/execute.js +338 -0
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/caching-sha2-password-auth.js +25 -62
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/clear-password-auth.js +39 -6
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/ed25519-password-auth.js +48 -16
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/handshake.js +198 -0
- package/dist/node_modules/mariadb/lib/cmd/handshake/{initial-handshake.js → auth/initial-handshake.js} +10 -8
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/native-password-auth.js +22 -9
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/pam-password-auth.js +9 -4
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/parsec-auth.js +115 -0
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/plugin-auth.js +12 -5
- package/dist/node_modules/mariadb/lib/cmd/handshake/auth/sha256-password-auth.js +44 -33
- package/dist/node_modules/mariadb/lib/cmd/handshake/authentication.js +335 -0
- package/dist/node_modules/mariadb/lib/cmd/handshake/client-capabilities.js +20 -19
- package/dist/node_modules/mariadb/lib/cmd/handshake/ssl-request.js +6 -3
- package/dist/node_modules/mariadb/lib/cmd/parser.js +861 -0
- package/dist/node_modules/mariadb/lib/cmd/ping.js +17 -18
- package/dist/node_modules/mariadb/lib/cmd/prepare.js +170 -0
- package/dist/node_modules/mariadb/lib/cmd/query.js +281 -144
- package/dist/node_modules/mariadb/lib/cmd/quit.js +9 -6
- package/dist/node_modules/mariadb/lib/cmd/reset.js +15 -19
- package/dist/node_modules/mariadb/lib/cmd/stream.js +21 -6
- package/dist/node_modules/mariadb/lib/config/cluster-options.js +23 -0
- package/dist/node_modules/mariadb/lib/config/connection-options.js +196 -132
- package/dist/node_modules/mariadb/lib/config/pool-options.js +27 -19
- package/dist/node_modules/mariadb/lib/connection-callback.js +492 -120
- package/dist/node_modules/mariadb/lib/connection-promise.js +372 -0
- package/dist/node_modules/mariadb/lib/connection.js +1739 -1016
- package/dist/node_modules/mariadb/lib/const/capabilities.js +36 -30
- package/dist/node_modules/mariadb/lib/const/collations.js +972 -36
- package/dist/node_modules/mariadb/lib/const/connection_status.js +3 -0
- package/dist/node_modules/mariadb/lib/const/error-code.js +35 -11
- package/dist/node_modules/mariadb/lib/const/field-detail.js +3 -0
- package/dist/node_modules/mariadb/lib/const/field-type.js +7 -4
- package/dist/node_modules/mariadb/lib/const/server-status.js +4 -1
- package/dist/node_modules/mariadb/lib/const/state-change.js +3 -0
- package/dist/node_modules/mariadb/lib/filtered-cluster-callback.js +136 -0
- package/dist/node_modules/mariadb/lib/filtered-cluster.js +118 -0
- package/dist/node_modules/mariadb/lib/io/compression-input-stream.js +14 -13
- package/dist/node_modules/mariadb/lib/io/compression-output-stream.js +21 -18
- package/dist/node_modules/mariadb/lib/io/packet-input-stream.js +75 -64
- package/dist/node_modules/mariadb/lib/io/packet-node-encoded.js +13 -9
- package/dist/node_modules/mariadb/lib/io/packet-node-iconv.js +12 -10
- package/dist/node_modules/mariadb/lib/io/packet-output-stream.js +402 -134
- package/dist/node_modules/mariadb/lib/io/packet.js +287 -202
- package/dist/node_modules/mariadb/lib/lru-prepare-cache.js +84 -0
- package/dist/node_modules/mariadb/lib/misc/connection-information.js +15 -32
- package/dist/node_modules/mariadb/lib/misc/errors.js +68 -25
- package/dist/node_modules/mariadb/lib/misc/parse.js +207 -711
- package/dist/node_modules/mariadb/lib/misc/utils.js +34 -62
- package/dist/node_modules/mariadb/lib/pool-callback.js +213 -174
- package/dist/node_modules/mariadb/lib/pool-promise.js +228 -94
- package/dist/node_modules/mariadb/lib/pool.js +951 -0
- package/dist/node_modules/mariadb/package.json +1 -1
- package/dist/node_modules/mariadb/promise.js +1 -34
- package/dist/node_modules/mariadb/types/callback.d.ts +207 -0
- package/dist/node_modules/mariadb/types/index.d.ts +94 -674
- package/dist/node_modules/mariadb/types/share.d.ts +804 -0
- package/dist/node_modules/qs/package.json +1 -1
- package/dist/server/actions/apps.js +2 -2
- package/dist/server/app-lifecycle.d.ts +1 -1
- package/dist/server/app-lifecycle.js +4 -4
- package/dist/server/models/application.d.ts +1 -1
- package/package.json +7 -7
- package/dist/node_modules/mariadb/lib/cmd/batch-rewrite.js +0 -372
- package/dist/node_modules/mariadb/lib/cmd/common-text-cmd.js +0 -427
- package/dist/node_modules/mariadb/lib/cmd/handshake/client-handshake-response.js +0 -126
- package/dist/node_modules/mariadb/lib/cmd/handshake/handshake.js +0 -292
- package/dist/node_modules/mariadb/lib/cmd/resultset.js +0 -607
- package/dist/node_modules/mariadb/lib/config/pool-cluster-options.js +0 -19
- package/dist/node_modules/mariadb/lib/filtered-pool-cluster.js +0 -81
- package/dist/node_modules/mariadb/lib/io/bulk-packet.js +0 -590
- package/dist/node_modules/mariadb/lib/io/rewrite-packet.js +0 -481
- package/dist/node_modules/mariadb/lib/pool-base.js +0 -611
- package/dist/node_modules/mariadb/lib/pool-cluster-callback.js +0 -66
- package/dist/node_modules/mariadb/lib/pool-cluster.js +0 -407
|
@@ -0,0 +1,861 @@
|
|
|
1
|
+
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
2
|
+
// Copyright (c) 2015-2025 MariaDB Corporation Ab
|
|
3
|
+
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const Command = require('./command');
|
|
7
|
+
const ServerStatus = require('../const/server-status');
|
|
8
|
+
const ColumnDefinition = require('./column-definition');
|
|
9
|
+
const Errors = require('../misc/errors');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const Parse = require('../misc/parse');
|
|
12
|
+
const BinaryDecoder = require('./decoder/binary-decoder');
|
|
13
|
+
const TextDecoder = require('./decoder/text-decoder');
|
|
14
|
+
const OkPacket = require('./class/ok-packet');
|
|
15
|
+
const StateChange = require('../const/state-change');
|
|
16
|
+
const Collations = require('../const/collations');
|
|
17
|
+
|
|
18
|
+
// Set of field names that are reserved for internal use
|
|
19
|
+
const privateFields = new Set([
|
|
20
|
+
'__defineGetter__',
|
|
21
|
+
'__defineSetter__',
|
|
22
|
+
'__lookupGetter__',
|
|
23
|
+
'__lookupSetter__',
|
|
24
|
+
'__proto__'
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Handle COM_QUERY / COM_STMT_EXECUTE results
|
|
29
|
+
* @see https://mariadb.com/kb/en/library/4-server-response-packets/
|
|
30
|
+
*/
|
|
31
|
+
class Parser extends Command {
|
|
32
|
+
/**
|
|
33
|
+
* Create a new Parser instance
|
|
34
|
+
*
|
|
35
|
+
* @param {Function} resolve - Promise resolve function
|
|
36
|
+
* @param {Function} reject - Promise reject function
|
|
37
|
+
* @param {Object} connOpts - Connection options
|
|
38
|
+
* @param {Object} cmdParam - Command parameters
|
|
39
|
+
*/
|
|
40
|
+
constructor(resolve, reject, connOpts, cmdParam) {
|
|
41
|
+
super(cmdParam, resolve, reject);
|
|
42
|
+
this._responseIndex = 0;
|
|
43
|
+
this._rows = [];
|
|
44
|
+
this.opts = cmdParam.opts ? Object.assign({}, connOpts, cmdParam.opts) : connOpts;
|
|
45
|
+
this.sql = cmdParam.sql;
|
|
46
|
+
this.initialValues = cmdParam.values;
|
|
47
|
+
this.canSkipMeta = false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Read Query response packet.
|
|
52
|
+
* Packet can be:
|
|
53
|
+
* - a result-set
|
|
54
|
+
* - an ERR_Packet
|
|
55
|
+
* - an OK_Packet
|
|
56
|
+
* - LOCAL_INFILE Packet
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} packet - Query response packet
|
|
59
|
+
* @param {Object} out - Output writer
|
|
60
|
+
* @param {Object} opts - Connection options
|
|
61
|
+
* @param {Object} info - Connection info
|
|
62
|
+
* @returns {Function|null} Next packet handler or null
|
|
63
|
+
*/
|
|
64
|
+
readResponsePacket(packet, out, opts, info) {
|
|
65
|
+
switch (packet.peek()) {
|
|
66
|
+
case 0x00: // OK response
|
|
67
|
+
return this.readOKPacket(packet, out, opts, info);
|
|
68
|
+
|
|
69
|
+
case 0xff: // ERROR response
|
|
70
|
+
return this.handleErrorPacket(packet, info);
|
|
71
|
+
|
|
72
|
+
case 0xfb: // LOCAL INFILE response
|
|
73
|
+
return this.readLocalInfile(packet, out, opts, info);
|
|
74
|
+
|
|
75
|
+
default: // Result set
|
|
76
|
+
return this.readResultSet(packet, info);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Handle error packet
|
|
82
|
+
*
|
|
83
|
+
* @param {Object} packet - Error packet
|
|
84
|
+
* @param {Object} info - Connection info
|
|
85
|
+
* @returns {null} Always returns null
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
handleErrorPacket(packet, info) {
|
|
89
|
+
// In case of timeout, free accumulated rows
|
|
90
|
+
this._columns = null;
|
|
91
|
+
|
|
92
|
+
const err = packet.readError(info, this.opts.logParam ? this.displaySql() : this.sql, this.cmdParam.stack);
|
|
93
|
+
|
|
94
|
+
// Force in transaction status, since query will have created a transaction if autocommit is off
|
|
95
|
+
// Goal is to avoid unnecessary COMMIT/ROLLBACK
|
|
96
|
+
info.status |= ServerStatus.STATUS_IN_TRANS;
|
|
97
|
+
|
|
98
|
+
return this.throwError(err, info);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Read result-set packets
|
|
103
|
+
* @see https://mariadb.com/kb/en/library/resultset/
|
|
104
|
+
*
|
|
105
|
+
* @param {Object} packet - Column count packet
|
|
106
|
+
* @param {Object} info - Connection information
|
|
107
|
+
* @returns {Function} Next packet handler
|
|
108
|
+
*/
|
|
109
|
+
readResultSet(packet, info) {
|
|
110
|
+
this._columnCount = packet.readUnsignedLength();
|
|
111
|
+
|
|
112
|
+
this._rows.push([]);
|
|
113
|
+
if (this.canSkipMeta && info.serverPermitSkipMeta && packet.readUInt8() === 0) {
|
|
114
|
+
// Command supports skipping meta
|
|
115
|
+
// Server permits it
|
|
116
|
+
// And tells that no columns follow, using prepare results
|
|
117
|
+
return this.handleSkippedMeta(info);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this._columns = [];
|
|
121
|
+
return (this.onPacketReceive = this.readColumn);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Handle skipped metadata case
|
|
126
|
+
*
|
|
127
|
+
* @param {Object} info - Connection information
|
|
128
|
+
* @returns {Function} Next packet handler
|
|
129
|
+
* @private
|
|
130
|
+
*/
|
|
131
|
+
handleSkippedMeta(info) {
|
|
132
|
+
this._columns = this.prepare.columns;
|
|
133
|
+
this._columnCount = this._columns.length;
|
|
134
|
+
this.emit('fields', this._columns);
|
|
135
|
+
this.setParser();
|
|
136
|
+
return (this.onPacketReceive = info.eofDeprecated ? this.readResultSetRow : this.readIntermediateEOF);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Read OK_Packet
|
|
141
|
+
* @see https://mariadb.com/kb/en/library/ok_packet/
|
|
142
|
+
*
|
|
143
|
+
* @param {Object} packet - OK_Packet
|
|
144
|
+
* @param {Object} out - Output writer
|
|
145
|
+
* @param {Object} opts - Connection options
|
|
146
|
+
* @param {Object} info - Connection information
|
|
147
|
+
* @returns {Function|null} Next packet handler or null
|
|
148
|
+
*/
|
|
149
|
+
readOKPacket(packet, out, opts, info) {
|
|
150
|
+
packet.skip(1); // Skip header
|
|
151
|
+
|
|
152
|
+
const affectedRows = packet.readUnsignedLength();
|
|
153
|
+
|
|
154
|
+
// Handle insertId based on options
|
|
155
|
+
let insertId = this.processInsertId(packet.readInsertId(), info);
|
|
156
|
+
info.status = packet.readUInt16();
|
|
157
|
+
|
|
158
|
+
const okPacket = new OkPacket(affectedRows, insertId, packet.readUInt16());
|
|
159
|
+
let mustRedirect = false;
|
|
160
|
+
|
|
161
|
+
// Process session state changes if present
|
|
162
|
+
if (info.status & ServerStatus.SESSION_STATE_CHANGED) {
|
|
163
|
+
mustRedirect = this.processSessionStateChanges(packet, info, opts);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Handle streaming case
|
|
167
|
+
if (this.inStream) {
|
|
168
|
+
this.handleNewRows(okPacket);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Handle redirection
|
|
172
|
+
if (mustRedirect) {
|
|
173
|
+
return null; // Redirection is handled asynchronously
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (
|
|
177
|
+
info.redirectRequest &&
|
|
178
|
+
(info.status & ServerStatus.STATUS_IN_TRANS) === 0 &&
|
|
179
|
+
(info.status & ServerStatus.MORE_RESULTS_EXISTS) === 0
|
|
180
|
+
) {
|
|
181
|
+
info.redirect(info.redirectRequest, this.okPacketSuccess.bind(this, okPacket, info));
|
|
182
|
+
} else {
|
|
183
|
+
this.okPacketSuccess(okPacket, info);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Process insertId based on connection options
|
|
191
|
+
*
|
|
192
|
+
* @param {BigInt} insertId - Raw insertId from packet
|
|
193
|
+
* @param {Object} info - Connection info
|
|
194
|
+
* @returns {BigInt|Number|String} Processed insertId
|
|
195
|
+
* @private
|
|
196
|
+
*/
|
|
197
|
+
processInsertId(insertId, info) {
|
|
198
|
+
if (this.opts.supportBigNumbers || this.opts.insertIdAsNumber) {
|
|
199
|
+
if (this.opts.insertIdAsNumber && this.opts.checkNumberRange && !Number.isSafeInteger(Number(insertId))) {
|
|
200
|
+
this.onPacketReceive = info.status & ServerStatus.MORE_RESULTS_EXISTS ? this.readResponsePacket : null;
|
|
201
|
+
this.throwUnexpectedError(
|
|
202
|
+
`last insert id value ${insertId} can't safely be converted to number`,
|
|
203
|
+
false,
|
|
204
|
+
info,
|
|
205
|
+
'42000',
|
|
206
|
+
Errors.ER_PARSING_PRECISION
|
|
207
|
+
);
|
|
208
|
+
return insertId;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (this.opts.supportBigNumbers && (this.opts.bigNumberStrings || !Number.isSafeInteger(Number(insertId)))) {
|
|
212
|
+
return insertId.toString();
|
|
213
|
+
} else {
|
|
214
|
+
return Number(insertId);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return insertId;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Process session state changes
|
|
223
|
+
*
|
|
224
|
+
* @param {Object} packet - Packet containing session state changes
|
|
225
|
+
* @param {Object} info - Connection information
|
|
226
|
+
* @param {Object} opts - Connection options
|
|
227
|
+
* @returns {Boolean} True if redirection is needed
|
|
228
|
+
* @private
|
|
229
|
+
*/
|
|
230
|
+
processSessionStateChanges(packet, info, opts) {
|
|
231
|
+
let mustRedirect = false;
|
|
232
|
+
packet.skipLengthCodedNumber();
|
|
233
|
+
|
|
234
|
+
while (packet.remaining()) {
|
|
235
|
+
const len = packet.readUnsignedLength();
|
|
236
|
+
if (len > 0) {
|
|
237
|
+
const subPacket = packet.subPacketLengthEncoded(len);
|
|
238
|
+
while (subPacket.remaining()) {
|
|
239
|
+
const type = subPacket.readUInt8();
|
|
240
|
+
switch (type) {
|
|
241
|
+
case StateChange.SESSION_TRACK_SYSTEM_VARIABLES:
|
|
242
|
+
mustRedirect = this.processSystemVariables(subPacket, info, opts) || mustRedirect;
|
|
243
|
+
break;
|
|
244
|
+
|
|
245
|
+
case StateChange.SESSION_TRACK_SCHEMA:
|
|
246
|
+
info.database = this.readSchemaChange(subPacket);
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return mustRedirect;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Process system variables changes
|
|
258
|
+
*
|
|
259
|
+
* @param {Object} subPacket - Packet containing system variables
|
|
260
|
+
* @param {Object} info - Connection information
|
|
261
|
+
* @param {Object} opts - Connection options
|
|
262
|
+
* @returns {Boolean} True if redirection is needed
|
|
263
|
+
* @private
|
|
264
|
+
*/
|
|
265
|
+
processSystemVariables(subPacket, info, opts) {
|
|
266
|
+
let mustRedirect = false;
|
|
267
|
+
let subSubPacket;
|
|
268
|
+
|
|
269
|
+
do {
|
|
270
|
+
subSubPacket = subPacket.subPacketLengthEncoded(subPacket.readUnsignedLength());
|
|
271
|
+
const variable = subSubPacket.readStringLengthEncoded();
|
|
272
|
+
const value = subSubPacket.readStringLengthEncoded();
|
|
273
|
+
|
|
274
|
+
switch (variable) {
|
|
275
|
+
case 'character_set_client':
|
|
276
|
+
info.collation = Collations.fromCharset(value);
|
|
277
|
+
if (info.collation === undefined) {
|
|
278
|
+
this.throwError(new Error(`unknown charset: '${value}'`), info);
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
opts.emit('collation', info.collation);
|
|
282
|
+
break;
|
|
283
|
+
|
|
284
|
+
case 'redirect_url':
|
|
285
|
+
if (value !== '') {
|
|
286
|
+
mustRedirect = true;
|
|
287
|
+
info.redirect(value, this.okPacketSuccess.bind(this, this.okPacket, info));
|
|
288
|
+
}
|
|
289
|
+
break;
|
|
290
|
+
|
|
291
|
+
case 'connection_id':
|
|
292
|
+
info.threadId = parseInt(value);
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
} while (subSubPacket.remaining() > 0);
|
|
296
|
+
|
|
297
|
+
return mustRedirect;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Read schema change from packet
|
|
302
|
+
*
|
|
303
|
+
* @param {Object} subPacket - Packet containing schema change
|
|
304
|
+
* @returns {String} New schema name
|
|
305
|
+
* @private
|
|
306
|
+
*/
|
|
307
|
+
readSchemaChange(subPacket) {
|
|
308
|
+
const subSubPacket = subPacket.subPacketLengthEncoded(subPacket.readUnsignedLength());
|
|
309
|
+
return subSubPacket.readStringLengthEncoded();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Handle OK packet success
|
|
314
|
+
*
|
|
315
|
+
* @param {Object} okPacket - OK packet
|
|
316
|
+
* @param {Object} info - Connection information
|
|
317
|
+
*/
|
|
318
|
+
okPacketSuccess(okPacket, info) {
|
|
319
|
+
if (this._responseIndex === 0) {
|
|
320
|
+
// Fast path for standard single result
|
|
321
|
+
if (info.status & ServerStatus.MORE_RESULTS_EXISTS) {
|
|
322
|
+
this._rows.push(okPacket);
|
|
323
|
+
this._responseIndex++;
|
|
324
|
+
return (this.onPacketReceive = this.readResponsePacket);
|
|
325
|
+
}
|
|
326
|
+
return this.success(this.opts.metaAsArray ? [okPacket, []] : okPacket);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
this._rows.push(okPacket);
|
|
330
|
+
|
|
331
|
+
if (info.status & ServerStatus.MORE_RESULTS_EXISTS) {
|
|
332
|
+
this._responseIndex++;
|
|
333
|
+
return (this.onPacketReceive = this.readResponsePacket);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (this.opts.metaAsArray) {
|
|
337
|
+
if (!this._meta) {
|
|
338
|
+
this._meta = new Array(this._responseIndex);
|
|
339
|
+
}
|
|
340
|
+
this._meta[this._responseIndex] = null;
|
|
341
|
+
this.success([this._rows, this._meta]);
|
|
342
|
+
} else {
|
|
343
|
+
this.success(this._rows);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Complete query with success
|
|
349
|
+
*
|
|
350
|
+
* @param {*} val - Result value
|
|
351
|
+
*/
|
|
352
|
+
success(val) {
|
|
353
|
+
this.successEnd(val);
|
|
354
|
+
this._columns = null;
|
|
355
|
+
this._rows = [];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Read column information metadata
|
|
360
|
+
* @see https://mariadb.com/kb/en/library/resultset/#column-definition-packet
|
|
361
|
+
*
|
|
362
|
+
* @param {Object} packet - Column definition packet
|
|
363
|
+
* @param {Object} out - Output writer
|
|
364
|
+
* @param {Object} opts - Connection options
|
|
365
|
+
* @param {Object} info - Connection information
|
|
366
|
+
*/
|
|
367
|
+
readColumn(packet, out, opts, info) {
|
|
368
|
+
this._columns.push(new ColumnDefinition(packet, info, this.opts.rowsAsArray));
|
|
369
|
+
|
|
370
|
+
// Last column
|
|
371
|
+
if (this._columns.length === this._columnCount) {
|
|
372
|
+
this.setParser();
|
|
373
|
+
|
|
374
|
+
if (this.canSkipMeta && info.serverPermitSkipMeta && this.prepare != null) {
|
|
375
|
+
// Server can skip meta, but have force sending it.
|
|
376
|
+
// Metadata have changed, updating prepare result accordingly
|
|
377
|
+
if (this._responseIndex === 0) this.prepare.columns = this._columns;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
this.emit('fields', this._columns);
|
|
381
|
+
this.onPacketReceive = info.eofDeprecated ? this.readResultSetRow : this.readIntermediateEOF;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Set up row parsers based on column information
|
|
387
|
+
*/
|
|
388
|
+
setParser() {
|
|
389
|
+
this._parseFunction = new Array(this._columnCount);
|
|
390
|
+
|
|
391
|
+
if (this.opts.typeCast) {
|
|
392
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
393
|
+
this._parseFunction[i] = this.readCastValue.bind(this, this._columns[i]);
|
|
394
|
+
}
|
|
395
|
+
} else {
|
|
396
|
+
const dataParser = this.binary ? BinaryDecoder.parser : TextDecoder.parser;
|
|
397
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
398
|
+
this._parseFunction[i] = dataParser(this._columns[i], this.opts);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (this.opts.rowsAsArray) {
|
|
403
|
+
this.parseRow = this.parseRowAsArray;
|
|
404
|
+
} else {
|
|
405
|
+
this.tableHeader = new Array(this._columnCount);
|
|
406
|
+
this.parseRow = this.binary ? this.parseRowStdBinary : this.parseRowStdText;
|
|
407
|
+
|
|
408
|
+
if (this.opts.nestTables) {
|
|
409
|
+
this.configureNestedTables();
|
|
410
|
+
} else {
|
|
411
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
412
|
+
this.tableHeader[i] = this._columns[i].name();
|
|
413
|
+
}
|
|
414
|
+
this.checkDuplicates();
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Configure nested tables format
|
|
421
|
+
* @private
|
|
422
|
+
*/
|
|
423
|
+
configureNestedTables() {
|
|
424
|
+
if (typeof this.opts.nestTables === 'string') {
|
|
425
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
426
|
+
this.tableHeader[i] = this._columns[i].table() + this.opts.nestTables + this._columns[i].name();
|
|
427
|
+
}
|
|
428
|
+
this.checkDuplicates();
|
|
429
|
+
} else if (this.opts.nestTables === true) {
|
|
430
|
+
this.parseRow = this.parseRowNested;
|
|
431
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
432
|
+
this.tableHeader[i] = [this._columns[i].table(), this._columns[i].name()];
|
|
433
|
+
}
|
|
434
|
+
this.checkNestTablesDuplicatesAndPrivateFields();
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Check for duplicate column names
|
|
440
|
+
*/
|
|
441
|
+
checkDuplicates() {
|
|
442
|
+
if (this.opts.checkDuplicate) {
|
|
443
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
444
|
+
if (this.tableHeader.indexOf(this.tableHeader[i], i + 1) > 0) {
|
|
445
|
+
const dupes = this.tableHeader.reduce(
|
|
446
|
+
(acc, v, i, arr) => (arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc),
|
|
447
|
+
[]
|
|
448
|
+
);
|
|
449
|
+
this.throwUnexpectedError(
|
|
450
|
+
`Error in results, duplicate field name \`${dupes[0]}\`.\n(see option \`checkDuplicate\`)`,
|
|
451
|
+
false,
|
|
452
|
+
null,
|
|
453
|
+
'42000',
|
|
454
|
+
Errors.ER_DUPLICATE_FIELD
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Check for duplicates and private fields in nested tables
|
|
463
|
+
*/
|
|
464
|
+
checkNestTablesDuplicatesAndPrivateFields() {
|
|
465
|
+
if (this.opts.checkDuplicate) {
|
|
466
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
467
|
+
for (let j = 0; j < i; j++) {
|
|
468
|
+
if (this.tableHeader[j][0] === this.tableHeader[i][0] && this.tableHeader[j][1] === this.tableHeader[i][1]) {
|
|
469
|
+
this.throwUnexpectedError(
|
|
470
|
+
`Error in results, duplicate field name \`${this.tableHeader[i][0]}\`.\`${this.tableHeader[i][1]}\`\n(see option \`checkDuplicate\`)`,
|
|
471
|
+
false,
|
|
472
|
+
null,
|
|
473
|
+
'42000',
|
|
474
|
+
Errors.ER_DUPLICATE_FIELD
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
482
|
+
if (privateFields.has(this.tableHeader[i][0])) {
|
|
483
|
+
this.throwUnexpectedError(
|
|
484
|
+
`Use of \`${this.tableHeader[i][0]}\` is not permitted with option \`nestTables\``,
|
|
485
|
+
false,
|
|
486
|
+
null,
|
|
487
|
+
'42000',
|
|
488
|
+
Errors.ER_PRIVATE_FIELDS_USE
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
// Continue parsing results to keep connection state
|
|
492
|
+
// but without assigning possible dangerous value
|
|
493
|
+
this.parseRow = () => {
|
|
494
|
+
return {};
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Read intermediate EOF
|
|
502
|
+
* Only for server before MariaDB 10.2 / MySQL 5.7 that doesn't have CLIENT_DEPRECATE_EOF capability
|
|
503
|
+
* @see https://mariadb.com/kb/en/library/eof_packet/
|
|
504
|
+
*
|
|
505
|
+
* @param {Object} packet - EOF Packet
|
|
506
|
+
* @param {Object} out - Output writer
|
|
507
|
+
* @param {Object} opts - Connection options
|
|
508
|
+
* @param {Object} info - Connection information
|
|
509
|
+
* @returns {Function|null} Next packet handler or null
|
|
510
|
+
*/
|
|
511
|
+
readIntermediateEOF(packet, out, opts, info) {
|
|
512
|
+
if (packet.peek() !== 0xfe) {
|
|
513
|
+
return this.throwNewError('Error in protocol, expected EOF packet', true, info, '42000', Errors.ER_EOF_EXPECTED);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Before MySQL 5.7.5, last EOF doesn't contain the good flag SERVER_MORE_RESULTS_EXISTS
|
|
517
|
+
// for OUT parameters. It must be checked here
|
|
518
|
+
// (5.7.5 does have the CLIENT_DEPRECATE_EOF capability, so this packet is not even sent)
|
|
519
|
+
packet.skip(3);
|
|
520
|
+
info.status = packet.readUInt16();
|
|
521
|
+
this.isOutParameter = info.status & ServerStatus.PS_OUT_PARAMS;
|
|
522
|
+
return (this.onPacketReceive = this.readResultSetRow);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Add new rows to the result set
|
|
527
|
+
*
|
|
528
|
+
* @param {Object} row - Row data
|
|
529
|
+
*/
|
|
530
|
+
handleNewRows(row) {
|
|
531
|
+
this._rows[this._responseIndex].push(row);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Check if packet is result-set end = EOF of OK_Packet with EOF header according to CLIENT_DEPRECATE_EOF capability
|
|
536
|
+
* or a result-set row
|
|
537
|
+
*
|
|
538
|
+
* @param packet current packet
|
|
539
|
+
* @param out output writer
|
|
540
|
+
* @param opts connection options
|
|
541
|
+
* @param info connection information
|
|
542
|
+
* @returns {*}
|
|
543
|
+
*/
|
|
544
|
+
readResultSetRow(packet, out, opts, info) {
|
|
545
|
+
if (packet.peek() >= 0xfe) {
|
|
546
|
+
if (packet.peek() === 0xff) {
|
|
547
|
+
//force in transaction status, since query will have created a transaction if autocommit is off
|
|
548
|
+
//goal is to avoid unnecessary COMMIT/ROLLBACK.
|
|
549
|
+
info.status |= ServerStatus.STATUS_IN_TRANS;
|
|
550
|
+
return this.throwError(
|
|
551
|
+
packet.readError(info, this.opts.logParam ? this.displaySql() : this.sql, this.cmdParam.err),
|
|
552
|
+
info
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if ((!info.eofDeprecated && packet.length() < 13) || (info.eofDeprecated && packet.length() < 0xffffff)) {
|
|
557
|
+
if (!info.eofDeprecated) {
|
|
558
|
+
packet.skip(3);
|
|
559
|
+
info.status = packet.readUInt16();
|
|
560
|
+
} else {
|
|
561
|
+
packet.skip(1); //skip header
|
|
562
|
+
packet.skipLengthCodedNumber(); //skip update count
|
|
563
|
+
packet.skipLengthCodedNumber(); //skip insert id
|
|
564
|
+
info.status = packet.readUInt16();
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (
|
|
568
|
+
info.redirectRequest &&
|
|
569
|
+
(info.status & ServerStatus.STATUS_IN_TRANS) === 0 &&
|
|
570
|
+
(info.status & ServerStatus.MORE_RESULTS_EXISTS) === 0
|
|
571
|
+
) {
|
|
572
|
+
info.redirect(info.redirectRequest, this.resultSetEndingPacketResult.bind(this, info));
|
|
573
|
+
} else {
|
|
574
|
+
this.resultSetEndingPacketResult(info);
|
|
575
|
+
}
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
this.handleNewRows(this.parseRow(packet));
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
resultSetEndingPacketResult(info) {
|
|
584
|
+
if (this.opts.metaAsArray) {
|
|
585
|
+
//return promise object as array :
|
|
586
|
+
// example for SELECT 1 =>
|
|
587
|
+
// [
|
|
588
|
+
// [ {"1": 1} ], //rows
|
|
589
|
+
// [ColumnDefinition] //meta
|
|
590
|
+
// ]
|
|
591
|
+
|
|
592
|
+
if (info.status & ServerStatus.MORE_RESULTS_EXISTS || this.isOutParameter) {
|
|
593
|
+
if (!this._meta) this._meta = [];
|
|
594
|
+
this._meta[this._responseIndex] = this._columns;
|
|
595
|
+
this._responseIndex++;
|
|
596
|
+
return (this.onPacketReceive = this.readResponsePacket);
|
|
597
|
+
}
|
|
598
|
+
if (this._responseIndex === 0) {
|
|
599
|
+
this.success([this._rows[0], this._columns]);
|
|
600
|
+
} else {
|
|
601
|
+
if (!this._meta) this._meta = [];
|
|
602
|
+
this._meta[this._responseIndex] = this._columns;
|
|
603
|
+
this.success([this._rows, this._meta]);
|
|
604
|
+
}
|
|
605
|
+
} else {
|
|
606
|
+
//return promise object as rows that have meta property :
|
|
607
|
+
// example for SELECT 1 =>
|
|
608
|
+
// [
|
|
609
|
+
// {"1": 1},
|
|
610
|
+
// meta: [ColumnDefinition]
|
|
611
|
+
// ]
|
|
612
|
+
Object.defineProperty(this._rows[this._responseIndex], 'meta', {
|
|
613
|
+
value: this._columns,
|
|
614
|
+
writable: true,
|
|
615
|
+
enumerable: this.opts.metaEnumerable
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
if (info.status & ServerStatus.MORE_RESULTS_EXISTS || this.isOutParameter) {
|
|
619
|
+
this._responseIndex++;
|
|
620
|
+
return (this.onPacketReceive = this.readResponsePacket);
|
|
621
|
+
}
|
|
622
|
+
this.success(this._responseIndex === 0 ? this._rows[0] : this._rows);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Display current SQL with parameters (truncated if too big)
|
|
628
|
+
*
|
|
629
|
+
* @returns {string}
|
|
630
|
+
*/
|
|
631
|
+
displaySql() {
|
|
632
|
+
if (this.opts && this.initialValues) {
|
|
633
|
+
if (this.sql.length > this.opts.debugLen) {
|
|
634
|
+
return this.sql.substring(0, this.opts.debugLen) + '...';
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
let sqlMsg = this.sql + ' - parameters:';
|
|
638
|
+
return Parser.logParameters(this.opts, sqlMsg, this.initialValues);
|
|
639
|
+
}
|
|
640
|
+
if (this.sql.length > this.opts.debugLen) {
|
|
641
|
+
return this.sql.substring(0, this.opts.debugLen) + '... - parameters:[]';
|
|
642
|
+
}
|
|
643
|
+
return this.sql + ' - parameters:[]';
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
static logParameters(opts, sqlMsg, values) {
|
|
647
|
+
if (opts.namedPlaceholders) {
|
|
648
|
+
sqlMsg += '{';
|
|
649
|
+
let first = true;
|
|
650
|
+
for (let key in values) {
|
|
651
|
+
if (first) {
|
|
652
|
+
first = false;
|
|
653
|
+
} else {
|
|
654
|
+
sqlMsg += ',';
|
|
655
|
+
}
|
|
656
|
+
sqlMsg += "'" + key + "':";
|
|
657
|
+
let param = values[key];
|
|
658
|
+
sqlMsg = Parser.logParam(sqlMsg, param);
|
|
659
|
+
if (sqlMsg.length > opts.debugLen) {
|
|
660
|
+
return sqlMsg.substring(0, opts.debugLen) + '...';
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
sqlMsg += '}';
|
|
664
|
+
} else {
|
|
665
|
+
sqlMsg += '[';
|
|
666
|
+
if (Array.isArray(values)) {
|
|
667
|
+
for (let i = 0; i < values.length; i++) {
|
|
668
|
+
if (i !== 0) sqlMsg += ',';
|
|
669
|
+
let param = values[i];
|
|
670
|
+
sqlMsg = Parser.logParam(sqlMsg, param);
|
|
671
|
+
if (sqlMsg.length > opts.debugLen) {
|
|
672
|
+
return sqlMsg.substring(0, opts.debugLen) + '...';
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
} else {
|
|
676
|
+
sqlMsg = Parser.logParam(sqlMsg, values);
|
|
677
|
+
if (sqlMsg.length > opts.debugLen) {
|
|
678
|
+
return sqlMsg.substring(0, opts.debugLen) + '...';
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
sqlMsg += ']';
|
|
682
|
+
}
|
|
683
|
+
return sqlMsg;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
parseRowAsArray(packet) {
|
|
687
|
+
const row = new Array(this._columnCount);
|
|
688
|
+
const nullBitMap = this.binary ? BinaryDecoder.newRow(packet, this._columns) : null;
|
|
689
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
690
|
+
row[i] = this._parseFunction[i](packet, this.opts, this.unexpectedError, nullBitMap, i);
|
|
691
|
+
}
|
|
692
|
+
return row;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
parseRowNested(packet) {
|
|
696
|
+
const row = {};
|
|
697
|
+
const nullBitMap = this.binary ? BinaryDecoder.newRow(packet, this._columns) : null;
|
|
698
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
699
|
+
if (!row[this.tableHeader[i][0]]) row[this.tableHeader[i][0]] = {};
|
|
700
|
+
row[this.tableHeader[i][0]][this.tableHeader[i][1]] = this._parseFunction[i](
|
|
701
|
+
packet,
|
|
702
|
+
this.opts,
|
|
703
|
+
this.unexpectedError,
|
|
704
|
+
nullBitMap,
|
|
705
|
+
i
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
return row;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
parseRowStdText(packet) {
|
|
712
|
+
const row = {};
|
|
713
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
714
|
+
row[this.tableHeader[i]] = this._parseFunction[i](packet, this.opts, this.unexpectedError);
|
|
715
|
+
}
|
|
716
|
+
return row;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
parseRowStdBinary(packet) {
|
|
720
|
+
const nullBitMap = BinaryDecoder.newRow(packet, this._columns);
|
|
721
|
+
const row = {};
|
|
722
|
+
for (let i = 0; i < this._columnCount; i++) {
|
|
723
|
+
row[this.tableHeader[i]] = this._parseFunction[i](packet, this.opts, this.unexpectedError, nullBitMap, i);
|
|
724
|
+
}
|
|
725
|
+
return row;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
readCastValue(column, packet, opts, unexpectedError, nullBitmap, index) {
|
|
729
|
+
if (this.binary) {
|
|
730
|
+
BinaryDecoder.castWrapper(column, packet, opts, nullBitmap, index);
|
|
731
|
+
} else {
|
|
732
|
+
TextDecoder.castWrapper(column, packet, opts, nullBitmap, index);
|
|
733
|
+
}
|
|
734
|
+
const dataParser = this.binary ? BinaryDecoder.parser : TextDecoder.parser;
|
|
735
|
+
return opts.typeCast(column, dataParser(column, opts).bind(null, packet, opts, unexpectedError, nullBitmap, index));
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
readLocalInfile(packet, out, opts, info) {
|
|
739
|
+
packet.skip(1); //skip header
|
|
740
|
+
out.startPacket(this);
|
|
741
|
+
|
|
742
|
+
const fileName = packet.readStringRemaining();
|
|
743
|
+
|
|
744
|
+
if (!Parse.validateFileName(this.sql, this.initialValues, fileName)) {
|
|
745
|
+
out.writeEmptyPacket();
|
|
746
|
+
const error = Errors.createError(
|
|
747
|
+
"LOCAL INFILE wrong filename. '" +
|
|
748
|
+
fileName +
|
|
749
|
+
"' doesn't correspond to query " +
|
|
750
|
+
this.sql +
|
|
751
|
+
'. Query cancelled. Check for malicious server / proxy',
|
|
752
|
+
Errors.ER_LOCAL_INFILE_WRONG_FILENAME,
|
|
753
|
+
info,
|
|
754
|
+
'HY000',
|
|
755
|
+
this.sql
|
|
756
|
+
);
|
|
757
|
+
process.nextTick(this.reject, error);
|
|
758
|
+
this.reject = null;
|
|
759
|
+
this.resolve = null;
|
|
760
|
+
return (this.onPacketReceive = this.readResponsePacket);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// this.sequenceNo = 2;
|
|
764
|
+
// this.compressSequenceNo = 2;
|
|
765
|
+
let stream;
|
|
766
|
+
try {
|
|
767
|
+
stream = this.opts.infileStreamFactory ? this.opts.infileStreamFactory(fileName) : fs.createReadStream(fileName);
|
|
768
|
+
} catch (e) {
|
|
769
|
+
out.writeEmptyPacket();
|
|
770
|
+
const error = Errors.createError(
|
|
771
|
+
`LOCAL INFILE infileStreamFactory failed`,
|
|
772
|
+
Errors.ER_LOCAL_INFILE_NOT_READABLE,
|
|
773
|
+
info,
|
|
774
|
+
'22000',
|
|
775
|
+
this.opts.logParam ? this.displaySql() : this.sql
|
|
776
|
+
);
|
|
777
|
+
error.cause = e;
|
|
778
|
+
process.nextTick(this.reject, error);
|
|
779
|
+
this.reject = null;
|
|
780
|
+
this.resolve = null;
|
|
781
|
+
return (this.onPacketReceive = this.readResponsePacket);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
stream.on(
|
|
785
|
+
'error',
|
|
786
|
+
function (err) {
|
|
787
|
+
out.writeEmptyPacket();
|
|
788
|
+
const error = Errors.createError(
|
|
789
|
+
`LOCAL INFILE command failed: ${err.message}`,
|
|
790
|
+
Errors.ER_LOCAL_INFILE_NOT_READABLE,
|
|
791
|
+
info,
|
|
792
|
+
'22000',
|
|
793
|
+
this.sql
|
|
794
|
+
);
|
|
795
|
+
process.nextTick(this.reject, error);
|
|
796
|
+
this.reject = null;
|
|
797
|
+
this.resolve = null;
|
|
798
|
+
}.bind(this)
|
|
799
|
+
);
|
|
800
|
+
stream.on('data', (chunk) => {
|
|
801
|
+
out.writeBuffer(chunk, 0, chunk.length);
|
|
802
|
+
});
|
|
803
|
+
stream.on('end', () => {
|
|
804
|
+
if (!out.isEmpty()) {
|
|
805
|
+
out.flushBuffer(false);
|
|
806
|
+
}
|
|
807
|
+
out.writeEmptyPacket();
|
|
808
|
+
});
|
|
809
|
+
this.onPacketReceive = this.readResponsePacket;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
static logParam(sqlMsg, param) {
|
|
813
|
+
if (param == null) {
|
|
814
|
+
sqlMsg += param === undefined ? 'undefined' : 'null';
|
|
815
|
+
} else {
|
|
816
|
+
switch (param.constructor.name) {
|
|
817
|
+
case 'Buffer':
|
|
818
|
+
sqlMsg += '0x' + param.toString('hex', 0, Math.min(1024, param.length)) + '';
|
|
819
|
+
break;
|
|
820
|
+
|
|
821
|
+
case 'String':
|
|
822
|
+
sqlMsg += "'" + param + "'";
|
|
823
|
+
break;
|
|
824
|
+
|
|
825
|
+
case 'Date':
|
|
826
|
+
sqlMsg += getStringDate(param);
|
|
827
|
+
break;
|
|
828
|
+
|
|
829
|
+
case 'Object':
|
|
830
|
+
sqlMsg += JSON.stringify(param);
|
|
831
|
+
break;
|
|
832
|
+
|
|
833
|
+
default:
|
|
834
|
+
sqlMsg += param.toString();
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
return sqlMsg;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
function getStringDate(param) {
|
|
842
|
+
return (
|
|
843
|
+
"'" +
|
|
844
|
+
('00' + (param.getMonth() + 1)).slice(-2) +
|
|
845
|
+
'/' +
|
|
846
|
+
('00' + param.getDate()).slice(-2) +
|
|
847
|
+
'/' +
|
|
848
|
+
param.getFullYear() +
|
|
849
|
+
' ' +
|
|
850
|
+
('00' + param.getHours()).slice(-2) +
|
|
851
|
+
':' +
|
|
852
|
+
('00' + param.getMinutes()).slice(-2) +
|
|
853
|
+
':' +
|
|
854
|
+
('00' + param.getSeconds()).slice(-2) +
|
|
855
|
+
'.' +
|
|
856
|
+
('000' + param.getMilliseconds()).slice(-3) +
|
|
857
|
+
"'"
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
module.exports = Parser;
|