@tachybase/module-multi-app 1.6.0 → 1.6.2

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.
Files changed (105) hide show
  1. package/README.md +34 -34
  2. package/README.zh-CN.md +34 -34
  3. package/client.d.ts +1 -1
  4. package/client.js +1 -1
  5. package/dist/externalVersion.js +5 -5
  6. package/dist/locale/en-US.json +48 -48
  7. package/dist/locale/es-ES.json +9 -9
  8. package/dist/locale/ko_KR.json +11 -11
  9. package/dist/locale/pt-BR.json +9 -9
  10. package/dist/locale/zh-CN.json +58 -58
  11. package/dist/node_modules/mariadb/callback.js +43 -8
  12. package/dist/node_modules/mariadb/check-node.js +30 -0
  13. package/dist/node_modules/mariadb/lib/cluster-callback.js +84 -0
  14. package/dist/node_modules/mariadb/lib/cluster.js +446 -0
  15. package/dist/node_modules/mariadb/lib/cmd/batch-bulk.js +576 -177
  16. package/dist/node_modules/mariadb/lib/cmd/change-user.js +54 -44
  17. package/dist/node_modules/mariadb/lib/cmd/class/ok-packet.js +3 -2
  18. package/dist/node_modules/mariadb/lib/cmd/class/prepare-cache-wrapper.js +46 -0
  19. package/dist/node_modules/mariadb/lib/cmd/class/prepare-result-packet.js +141 -0
  20. package/dist/node_modules/mariadb/lib/cmd/class/prepare-wrapper.js +70 -0
  21. package/dist/node_modules/mariadb/lib/cmd/close-prepare.js +38 -0
  22. package/dist/node_modules/mariadb/lib/cmd/column-definition.js +145 -47
  23. package/dist/node_modules/mariadb/lib/cmd/command.js +41 -75
  24. package/dist/node_modules/mariadb/lib/cmd/decoder/binary-decoder.js +282 -0
  25. package/dist/node_modules/mariadb/lib/cmd/decoder/text-decoder.js +210 -0
  26. package/dist/node_modules/mariadb/lib/cmd/{common-binary-cmd.js → encoder/binary-encoder.js} +34 -77
  27. package/dist/node_modules/mariadb/lib/cmd/encoder/text-encoder.js +311 -0
  28. package/dist/node_modules/mariadb/lib/cmd/execute-stream.js +61 -0
  29. package/dist/node_modules/mariadb/lib/cmd/execute.js +338 -0
  30. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/caching-sha2-password-auth.js +25 -62
  31. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/clear-password-auth.js +39 -6
  32. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/ed25519-password-auth.js +48 -16
  33. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/handshake.js +198 -0
  34. package/dist/node_modules/mariadb/lib/cmd/handshake/{initial-handshake.js → auth/initial-handshake.js} +10 -8
  35. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/native-password-auth.js +22 -9
  36. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/pam-password-auth.js +9 -4
  37. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/parsec-auth.js +115 -0
  38. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/plugin-auth.js +12 -5
  39. package/dist/node_modules/mariadb/lib/cmd/handshake/auth/sha256-password-auth.js +44 -33
  40. package/dist/node_modules/mariadb/lib/cmd/handshake/authentication.js +335 -0
  41. package/dist/node_modules/mariadb/lib/cmd/handshake/client-capabilities.js +20 -19
  42. package/dist/node_modules/mariadb/lib/cmd/handshake/ssl-request.js +6 -3
  43. package/dist/node_modules/mariadb/lib/cmd/parser.js +861 -0
  44. package/dist/node_modules/mariadb/lib/cmd/ping.js +17 -18
  45. package/dist/node_modules/mariadb/lib/cmd/prepare.js +170 -0
  46. package/dist/node_modules/mariadb/lib/cmd/query.js +281 -144
  47. package/dist/node_modules/mariadb/lib/cmd/quit.js +9 -6
  48. package/dist/node_modules/mariadb/lib/cmd/reset.js +15 -19
  49. package/dist/node_modules/mariadb/lib/cmd/stream.js +21 -6
  50. package/dist/node_modules/mariadb/lib/config/cluster-options.js +23 -0
  51. package/dist/node_modules/mariadb/lib/config/connection-options.js +196 -132
  52. package/dist/node_modules/mariadb/lib/config/pool-options.js +27 -19
  53. package/dist/node_modules/mariadb/lib/connection-callback.js +492 -120
  54. package/dist/node_modules/mariadb/lib/connection-promise.js +372 -0
  55. package/dist/node_modules/mariadb/lib/connection.js +1739 -1016
  56. package/dist/node_modules/mariadb/lib/const/capabilities.js +36 -30
  57. package/dist/node_modules/mariadb/lib/const/collations.js +972 -36
  58. package/dist/node_modules/mariadb/lib/const/connection_status.js +3 -0
  59. package/dist/node_modules/mariadb/lib/const/error-code.js +35 -11
  60. package/dist/node_modules/mariadb/lib/const/field-detail.js +3 -0
  61. package/dist/node_modules/mariadb/lib/const/field-type.js +7 -4
  62. package/dist/node_modules/mariadb/lib/const/server-status.js +4 -1
  63. package/dist/node_modules/mariadb/lib/const/state-change.js +3 -0
  64. package/dist/node_modules/mariadb/lib/filtered-cluster-callback.js +136 -0
  65. package/dist/node_modules/mariadb/lib/filtered-cluster.js +118 -0
  66. package/dist/node_modules/mariadb/lib/io/compression-input-stream.js +14 -13
  67. package/dist/node_modules/mariadb/lib/io/compression-output-stream.js +21 -18
  68. package/dist/node_modules/mariadb/lib/io/packet-input-stream.js +75 -64
  69. package/dist/node_modules/mariadb/lib/io/packet-node-encoded.js +13 -9
  70. package/dist/node_modules/mariadb/lib/io/packet-node-iconv.js +12 -10
  71. package/dist/node_modules/mariadb/lib/io/packet-output-stream.js +402 -134
  72. package/dist/node_modules/mariadb/lib/io/packet.js +287 -202
  73. package/dist/node_modules/mariadb/lib/lru-prepare-cache.js +84 -0
  74. package/dist/node_modules/mariadb/lib/misc/connection-information.js +15 -32
  75. package/dist/node_modules/mariadb/lib/misc/errors.js +68 -25
  76. package/dist/node_modules/mariadb/lib/misc/parse.js +207 -711
  77. package/dist/node_modules/mariadb/lib/misc/utils.js +34 -62
  78. package/dist/node_modules/mariadb/lib/pool-callback.js +213 -174
  79. package/dist/node_modules/mariadb/lib/pool-promise.js +228 -94
  80. package/dist/node_modules/mariadb/lib/pool.js +951 -0
  81. package/dist/node_modules/mariadb/package.json +1 -1
  82. package/dist/node_modules/mariadb/promise.js +1 -34
  83. package/dist/node_modules/mariadb/types/callback.d.ts +207 -0
  84. package/dist/node_modules/mariadb/types/index.d.ts +94 -674
  85. package/dist/node_modules/mariadb/types/share.d.ts +804 -0
  86. package/dist/node_modules/qs/package.json +1 -1
  87. package/dist/server/actions/apps.js +2 -2
  88. package/dist/server/app-lifecycle.d.ts +1 -1
  89. package/dist/server/app-lifecycle.js +4 -4
  90. package/dist/server/models/application.d.ts +1 -1
  91. package/package.json +7 -7
  92. package/server.d.ts +2 -2
  93. package/server.js +1 -1
  94. package/dist/node_modules/mariadb/lib/cmd/batch-rewrite.js +0 -372
  95. package/dist/node_modules/mariadb/lib/cmd/common-text-cmd.js +0 -427
  96. package/dist/node_modules/mariadb/lib/cmd/handshake/client-handshake-response.js +0 -126
  97. package/dist/node_modules/mariadb/lib/cmd/handshake/handshake.js +0 -292
  98. package/dist/node_modules/mariadb/lib/cmd/resultset.js +0 -607
  99. package/dist/node_modules/mariadb/lib/config/pool-cluster-options.js +0 -19
  100. package/dist/node_modules/mariadb/lib/filtered-pool-cluster.js +0 -81
  101. package/dist/node_modules/mariadb/lib/io/bulk-packet.js +0 -590
  102. package/dist/node_modules/mariadb/lib/io/rewrite-packet.js +0 -481
  103. package/dist/node_modules/mariadb/lib/pool-base.js +0 -611
  104. package/dist/node_modules/mariadb/lib/pool-cluster-callback.js +0 -66
  105. package/dist/node_modules/mariadb/lib/pool-cluster.js +0 -407
@@ -0,0 +1,311 @@
1
+ // SPDX-License-Identifier: LGPL-2.1-or-later
2
+ // Copyright (c) 2015-2024 MariaDB Corporation Ab
3
+
4
+ 'use strict';
5
+
6
+ const QUOTE = 0x27;
7
+
8
+ // Cache common GeoJSON types
9
+ const GEO_TYPES = new Set([
10
+ 'Point',
11
+ 'LineString',
12
+ 'Polygon',
13
+ 'MultiPoint',
14
+ 'MultiLineString',
15
+ 'MultiPolygon',
16
+ 'GeometryCollection'
17
+ ]);
18
+
19
+ // Optimized function to pad numbers with leading zeros
20
+ const formatDigit = function (val, significantDigit) {
21
+ const str = `${val}`;
22
+ return str.length < significantDigit ? '0'.repeat(significantDigit - str.length) + str : str;
23
+ };
24
+
25
+ class TextEncoder {
26
+ /**
27
+ * Write (and escape) current parameter value to output writer
28
+ *
29
+ * @param out output writer
30
+ * @param value current parameter. Expected to be non-null
31
+ * @param opts connection options
32
+ * @param info connection information
33
+ */
34
+ static writeParam(out, value, opts, info) {
35
+ switch (typeof value) {
36
+ case 'boolean':
37
+ out.writeStringAscii(value ? 'true' : 'false');
38
+ break;
39
+ case 'bigint':
40
+ case 'number':
41
+ out.writeStringAscii(`${value}`);
42
+ break;
43
+ case 'string':
44
+ out.writeStringEscapeQuote(value);
45
+ break;
46
+ case 'object':
47
+ if (Object.prototype.toString.call(value) === '[object Date]') {
48
+ out.writeStringAscii(TextEncoder.getLocalDate(value));
49
+ } else if (Buffer.isBuffer(value)) {
50
+ out.writeStringAscii("_BINARY '");
51
+ out.writeBufferEscape(value);
52
+ out.writeInt8(QUOTE);
53
+ } else if (typeof value.toSqlString === 'function') {
54
+ out.writeStringEscapeQuote(String(value.toSqlString()));
55
+ } else if (Array.isArray(value)) {
56
+ if (opts.arrayParenthesis) {
57
+ out.writeStringAscii('(');
58
+ }
59
+ for (let i = 0; i < value.length; i++) {
60
+ if (i !== 0) out.writeStringAscii(',');
61
+ if (value[i] == null) {
62
+ out.writeStringAscii('NULL');
63
+ } else TextEncoder.writeParam(out, value[i], opts, info);
64
+ }
65
+
66
+ if (opts.arrayParenthesis) {
67
+ out.writeStringAscii(')');
68
+ }
69
+ } else {
70
+ if (value.type != null && GEO_TYPES.has(value.type)) {
71
+ //GeoJSON format.
72
+ const isMariaDb = info.isMariaDB();
73
+ const prefix =
74
+ (isMariaDb && info.hasMinVersion(10, 1, 4)) || (!isMariaDb && info.hasMinVersion(5, 7, 6)) ? 'ST_' : '';
75
+
76
+ switch (value.type) {
77
+ case 'Point':
78
+ out.writeStringAscii(
79
+ prefix + "PointFromText('POINT(" + TextEncoder.geoPointToString(value.coordinates) + ")')"
80
+ );
81
+ break;
82
+
83
+ case 'LineString':
84
+ out.writeStringAscii(
85
+ prefix + "LineFromText('LINESTRING(" + TextEncoder.geoArrayPointToString(value.coordinates) + ")')"
86
+ );
87
+ break;
88
+
89
+ case 'Polygon':
90
+ out.writeStringAscii(
91
+ prefix +
92
+ "PolygonFromText('POLYGON(" +
93
+ TextEncoder.geoMultiArrayPointToString(value.coordinates) +
94
+ ")')"
95
+ );
96
+ break;
97
+
98
+ case 'MultiPoint':
99
+ out.writeStringAscii(
100
+ prefix +
101
+ "MULTIPOINTFROMTEXT('MULTIPOINT(" +
102
+ TextEncoder.geoArrayPointToString(value.coordinates) +
103
+ ")')"
104
+ );
105
+ break;
106
+
107
+ case 'MultiLineString':
108
+ out.writeStringAscii(
109
+ prefix +
110
+ "MLineFromText('MULTILINESTRING(" +
111
+ TextEncoder.geoMultiArrayPointToString(value.coordinates) +
112
+ ")')"
113
+ );
114
+ break;
115
+
116
+ case 'MultiPolygon':
117
+ out.writeStringAscii(
118
+ prefix +
119
+ "MPolyFromText('MULTIPOLYGON(" +
120
+ TextEncoder.geoMultiPolygonToString(value.coordinates) +
121
+ ")')"
122
+ );
123
+ break;
124
+
125
+ case 'GeometryCollection':
126
+ out.writeStringAscii(
127
+ prefix +
128
+ "GeomCollFromText('GEOMETRYCOLLECTION(" +
129
+ TextEncoder.geometricCollectionToString(value.geometries) +
130
+ ")')"
131
+ );
132
+ break;
133
+ }
134
+ } else if (String === value.constructor) {
135
+ out.writeStringEscapeQuote(value);
136
+ break;
137
+ } else {
138
+ if (opts.permitSetMultiParamEntries) {
139
+ let first = true;
140
+ for (const key in value) {
141
+ const val = value[key];
142
+ if (typeof val === 'function') continue;
143
+
144
+ if (first) {
145
+ first = false;
146
+ } else {
147
+ out.writeStringAscii(',');
148
+ }
149
+
150
+ out.writeString('`' + key + '`');
151
+
152
+ if (val == null) {
153
+ out.writeStringAscii('=NULL');
154
+ } else {
155
+ out.writeStringAscii('=');
156
+ TextEncoder.writeParam(out, val, opts, info);
157
+ }
158
+ }
159
+ if (first) out.writeStringEscapeQuote(JSON.stringify(value));
160
+ } else {
161
+ out.writeStringEscapeQuote(JSON.stringify(value));
162
+ }
163
+ }
164
+ }
165
+ break;
166
+ }
167
+ }
168
+
169
+ static geometricCollectionToString(geo) {
170
+ if (!geo) return '';
171
+
172
+ const len = geo.length;
173
+ let st = '';
174
+
175
+ for (let i = 0; i < len; i++) {
176
+ const item = geo[i];
177
+ //GeoJSON format.
178
+ if (i !== 0) st += ',';
179
+
180
+ switch (item.type) {
181
+ case 'Point':
182
+ st += `POINT(${TextEncoder.geoPointToString(item.coordinates)})`;
183
+ break;
184
+
185
+ case 'LineString':
186
+ st += `LINESTRING(${TextEncoder.geoArrayPointToString(item.coordinates)})`;
187
+ break;
188
+
189
+ case 'Polygon':
190
+ st += `POLYGON(${TextEncoder.geoMultiArrayPointToString(item.coordinates)})`;
191
+ break;
192
+
193
+ case 'MultiPoint':
194
+ st += `MULTIPOINT(${TextEncoder.geoArrayPointToString(item.coordinates)})`;
195
+ break;
196
+
197
+ case 'MultiLineString':
198
+ st += `MULTILINESTRING(${TextEncoder.geoMultiArrayPointToString(item.coordinates)})`;
199
+ break;
200
+
201
+ case 'MultiPolygon':
202
+ st += `MULTIPOLYGON(${TextEncoder.geoMultiPolygonToString(item.coordinates)})`;
203
+ break;
204
+ }
205
+ }
206
+ return st;
207
+ }
208
+
209
+ static geoMultiPolygonToString(coords) {
210
+ if (!coords) return '';
211
+
212
+ const len = coords.length;
213
+ if (len === 0) return '';
214
+
215
+ let st = '(';
216
+
217
+ for (let i = 0; i < len; i++) {
218
+ if (i !== 0) st += ',(';
219
+ st += TextEncoder.geoMultiArrayPointToString(coords[i]) + ')';
220
+ }
221
+
222
+ return st;
223
+ }
224
+
225
+ static geoMultiArrayPointToString(coords) {
226
+ if (!coords) return '';
227
+
228
+ const len = coords.length;
229
+ if (len === 0) return '';
230
+
231
+ let st = '(';
232
+
233
+ for (let i = 0; i < len; i++) {
234
+ if (i !== 0) st += ',(';
235
+ st += TextEncoder.geoArrayPointToString(coords[i]) + ')';
236
+ }
237
+
238
+ return st;
239
+ }
240
+
241
+ static geoArrayPointToString(coords) {
242
+ if (!coords) return '';
243
+
244
+ const len = coords.length;
245
+ if (len === 0) return '';
246
+
247
+ let st = '';
248
+
249
+ for (let i = 0; i < len; i++) {
250
+ if (i !== 0) st += ',';
251
+ st += TextEncoder.geoPointToString(coords[i]);
252
+ }
253
+
254
+ return st;
255
+ }
256
+
257
+ static geoPointToString(coords) {
258
+ if (!coords) return '';
259
+ const x = isNaN(coords[0]) ? '' : coords[0];
260
+ const y = isNaN(coords[1]) ? '' : coords[1];
261
+ return x + ' ' + y;
262
+ }
263
+
264
+ static getLocalDate(date) {
265
+ const year = date.getFullYear();
266
+ const month = date.getMonth() + 1;
267
+ const day = date.getDate();
268
+ const hours = date.getHours();
269
+ const minutes = date.getMinutes();
270
+ const seconds = date.getSeconds();
271
+ const ms = date.getMilliseconds();
272
+
273
+ const d = "'" + year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
274
+
275
+ if (ms === 0) return d + "'";
276
+
277
+ return d + '.' + (ms < 10 ? '00' : ms < 100 ? '0' : '') + ms + "'";
278
+ }
279
+
280
+ static getFixedFormatDate(date) {
281
+ const year = date.getFullYear();
282
+ const mon = date.getMonth() + 1;
283
+ const day = date.getDate();
284
+ const hour = date.getHours();
285
+ const min = date.getMinutes();
286
+ const sec = date.getSeconds();
287
+ const ms = date.getMilliseconds();
288
+
289
+ let result =
290
+ "'" +
291
+ formatDigit(year, 4) +
292
+ '-' +
293
+ formatDigit(mon, 2) +
294
+ '-' +
295
+ formatDigit(day, 2) +
296
+ ' ' +
297
+ formatDigit(hour, 2) +
298
+ ':' +
299
+ formatDigit(min, 2) +
300
+ ':' +
301
+ formatDigit(sec, 2);
302
+
303
+ if (ms > 0) {
304
+ result += '.' + formatDigit(ms, 3);
305
+ }
306
+
307
+ return result + "'";
308
+ }
309
+ }
310
+
311
+ module.exports = TextEncoder;
@@ -0,0 +1,61 @@
1
+ // SPDX-License-Identifier: LGPL-2.1-or-later
2
+ // Copyright (c) 2015-2024 MariaDB Corporation Ab
3
+
4
+ 'use strict';
5
+
6
+ const Execute = require('./execute');
7
+ const { Readable } = require('stream');
8
+
9
+ /**
10
+ * Protocol COM_STMT_EXECUTE with streaming events.
11
+ * see : https://mariadb.com/kb/en/com_stmt_execute/
12
+ */
13
+ class ExecuteStream extends Execute {
14
+ constructor(cmdParam, connOpts, prepare, socket) {
15
+ super(
16
+ () => {},
17
+ () => {},
18
+ connOpts,
19
+ cmdParam,
20
+ prepare
21
+ );
22
+ this.socket = socket;
23
+ this.inStream = new Readable({
24
+ objectMode: true,
25
+ read: () => {
26
+ this.socket.resume();
27
+ }
28
+ });
29
+
30
+ this.on('fields', function (meta) {
31
+ this.inStream.emit('fields', meta);
32
+ });
33
+
34
+ this.on('error', function (err) {
35
+ this.inStream.emit('error', err);
36
+ });
37
+
38
+ this.on('close', function (err) {
39
+ this.inStream.emit('error', err);
40
+ });
41
+
42
+ this.on('end', function (err) {
43
+ if (err) this.inStream.emit('error', err);
44
+ this.socket.resume();
45
+ this.inStream.push(null);
46
+ });
47
+
48
+ this.inStream.close = function () {
49
+ this.handleNewRows = () => {};
50
+ this.socket.resume();
51
+ }.bind(this);
52
+ }
53
+
54
+ handleNewRows(row) {
55
+ if (!this.inStream.push(row)) {
56
+ this.socket.pause();
57
+ }
58
+ }
59
+ }
60
+
61
+ module.exports = ExecuteStream;
@@ -0,0 +1,338 @@
1
+ // SPDX-License-Identifier: LGPL-2.1-or-later
2
+ // Copyright (c) 2015-2024 MariaDB Corporation Ab
3
+
4
+ 'use strict';
5
+
6
+ const Parser = require('./parser');
7
+ const Errors = require('../misc/errors');
8
+ const BinaryEncoder = require('./encoder/binary-encoder');
9
+ const FieldType = require('../const/field-type');
10
+ const Parse = require('../misc/parse');
11
+
12
+ /**
13
+ * Protocol COM_STMT_EXECUTE
14
+ * see : https://mariadb.com/kb/en/com_stmt_execute/
15
+ */
16
+ class Execute extends Parser {
17
+ constructor(resolve, reject, connOpts, cmdParam, prepare) {
18
+ super(resolve, reject, connOpts, cmdParam);
19
+ this.binary = true;
20
+ this.prepare = prepare;
21
+ this.canSkipMeta = true;
22
+ }
23
+
24
+ /**
25
+ * Send COM_QUERY
26
+ *
27
+ * @param out output writer
28
+ * @param opts connection options
29
+ * @param info connection information
30
+ */
31
+ start(out, opts, info) {
32
+ this.onPacketReceive = this.readResponsePacket;
33
+ this.values = [];
34
+
35
+ if (this.opts.namedPlaceholders) {
36
+ if (this.prepare) {
37
+ // using named placeholders, so change values accordingly
38
+ this.values = new Array(this.prepare.parameterCount);
39
+ this.placeHolderIndex = this.prepare._placeHolderIndex;
40
+ } else {
41
+ const res = Parse.searchPlaceholder(this.sql);
42
+ this.placeHolderIndex = res.placeHolderIndex;
43
+ this.values = new Array(this.placeHolderIndex.length);
44
+ }
45
+ if (this.initialValues) {
46
+ for (let i = 0; i < this.placeHolderIndex.length; i++) {
47
+ this.values[i] = this.initialValues[this.placeHolderIndex[i]];
48
+ }
49
+ }
50
+ } else {
51
+ if (this.initialValues)
52
+ this.values = Array.isArray(this.initialValues) ? this.initialValues : [this.initialValues];
53
+ }
54
+ this.parameterCount = this.prepare ? this.prepare.parameterCount : this.values.length;
55
+
56
+ if (!this.validateParameters(info)) return;
57
+
58
+ // fill parameter data type
59
+ this.parametersType = new Array(this.parameterCount);
60
+ let hasLongData = false; // send long data
61
+ let val;
62
+ for (let i = 0; i < this.parameterCount; i++) {
63
+ val = this.values[i];
64
+ // special check for GEOJSON that can be null even if object is not
65
+ if (
66
+ val &&
67
+ val.type != null &&
68
+ [
69
+ 'Point',
70
+ 'LineString',
71
+ 'Polygon',
72
+ 'MultiPoint',
73
+ 'MultiLineString',
74
+ 'MultiPolygon',
75
+ 'GeometryCollection'
76
+ ].includes(val.type)
77
+ ) {
78
+ const geoBuff = BinaryEncoder.getBufferFromGeometryValue(val);
79
+ if (geoBuff == null) {
80
+ this.values[i] = null;
81
+ val = null;
82
+ } else {
83
+ this.values[i] = Buffer.concat([
84
+ Buffer.from([0, 0, 0, 0]), // SRID
85
+ geoBuff // WKB
86
+ ]);
87
+ val = this.values[i];
88
+ }
89
+ }
90
+ if (val == null) {
91
+ this.parametersType[i] = NULL_PARAM_TYPE;
92
+ } else {
93
+ switch (typeof val) {
94
+ case 'boolean':
95
+ this.parametersType[i] = BOOLEAN_TYPE;
96
+ break;
97
+ case 'bigint':
98
+ if (val >= 2n ** 63n) {
99
+ this.parametersType[i] = BIG_BIGINT_TYPE;
100
+ } else {
101
+ this.parametersType[i] = BIGINT_TYPE;
102
+ }
103
+ break;
104
+ case 'number':
105
+ // additional verification, to permit query without type,
106
+ // like 'SELECT ?' returning same type of value
107
+ if (Number.isInteger(val) && val >= -2147483648 && val < 2147483647) {
108
+ this.parametersType[i] = INT_TYPE;
109
+ break;
110
+ }
111
+ this.parametersType[i] = DOUBLE_TYPE;
112
+ break;
113
+ case 'string':
114
+ this.parametersType[i] = STRING_TYPE;
115
+ break;
116
+ case 'object':
117
+ if (Object.prototype.toString.call(val) === '[object Date]') {
118
+ this.parametersType[i] = DATE_TYPE;
119
+ } else if (Buffer.isBuffer(val)) {
120
+ if (val.length < 16384 || !this.prepare) {
121
+ this.parametersType[i] = BLOB_TYPE;
122
+ } else {
123
+ this.parametersType[i] = LONGBLOB_TYPE;
124
+ hasLongData = true;
125
+ }
126
+ } else if (typeof val.toSqlString === 'function') {
127
+ this.parametersType[i] = STRING_FCT_TYPE;
128
+ } else if (typeof val.pipe === 'function' && typeof val.read === 'function') {
129
+ hasLongData = true;
130
+ this.parametersType[i] = STREAM_TYPE;
131
+ } else if (String === val.constructor) {
132
+ this.parametersType[i] = STRING_TOSTR_TYPE;
133
+ } else {
134
+ this.parametersType[i] = STRINGIFY_TYPE;
135
+ }
136
+ break;
137
+ }
138
+ }
139
+ }
140
+
141
+ // send long data using COM_STMT_SEND_LONG_DATA
142
+ this.longDataStep = false; // send long data
143
+ if (hasLongData) {
144
+ for (let i = 0; i < this.parameterCount; i++) {
145
+ if (this.parametersType[i].isLongData()) {
146
+ if (opts.logger.query)
147
+ opts.logger.query(
148
+ `EXECUTE: (${this.prepare ? this.prepare.id : -1}) sql: ${opts.logParam ? this.displaySql() : this.sql}`
149
+ );
150
+ if (!this.longDataStep) {
151
+ this.longDataStep = true;
152
+ this.registerStreamSendEvent(out, info);
153
+ this.currentParam = i;
154
+ }
155
+ this.sendComStmtLongData(out, info, this.values[i]);
156
+ return;
157
+ }
158
+ }
159
+ }
160
+
161
+ if (!this.longDataStep) {
162
+ // no stream parameter, so can send directly
163
+ if (opts.logger.query)
164
+ opts.logger.query(
165
+ `EXECUTE: (${this.prepare ? this.prepare.id : -1}) sql: ${opts.logParam ? this.displaySql() : this.sql}`
166
+ );
167
+ this.sendComStmtExecute(out, info);
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Validate that parameters exists and are defined.
173
+ *
174
+ * @param info connection info
175
+ * @returns {boolean} return false if any error occur.
176
+ */
177
+ validateParameters(info) {
178
+ //validate parameter size.
179
+ if (this.parameterCount > this.values.length) {
180
+ this.sendCancelled(
181
+ `Parameter at position ${this.values.length} is not set\\nsql: ${
182
+ this.opts.logParam ? this.displaySql() : this.sql
183
+ }`,
184
+ Errors.ER_MISSING_PARAMETER,
185
+ info
186
+ );
187
+ return false;
188
+ }
189
+
190
+ // validate placeholder
191
+ if (this.opts.namedPlaceholders && this.placeHolderIndex) {
192
+ for (let i = 0; i < this.parameterCount; i++) {
193
+ if (this.values[i] === undefined) {
194
+ let errMsg = `Parameter named ${this.placeHolderIndex[i]} is not set`;
195
+ if (this.placeHolderIndex.length < this.parameterCount) {
196
+ errMsg = `Command expect ${this.parameterCount} parameters, but found only ${this.placeHolderIndex.length} named parameters. You probably use question mark in place of named parameters`;
197
+ }
198
+ this.sendCancelled(errMsg, Errors.ER_PARAMETER_UNDEFINED, info);
199
+ return false;
200
+ }
201
+ }
202
+ }
203
+ return true;
204
+ }
205
+
206
+ sendComStmtLongData(out, info, value) {
207
+ out.startPacket(this);
208
+ out.writeInt8(0x18);
209
+ out.writeInt32(this.prepare.id);
210
+ out.writeInt16(this.currentParam);
211
+
212
+ if (Buffer.isBuffer(value)) {
213
+ out.writeBuffer(value, 0, value.length);
214
+ out.flush();
215
+ this.currentParam++;
216
+ return this.paramWritten();
217
+ }
218
+ this.sending = true;
219
+
220
+ // streaming
221
+ value.on('data', function (chunk) {
222
+ out.writeBuffer(chunk, 0, chunk.length);
223
+ });
224
+
225
+ value.on(
226
+ 'end',
227
+ function () {
228
+ out.flush();
229
+ this.currentParam++;
230
+ this.paramWritten();
231
+ }.bind(this)
232
+ );
233
+ }
234
+
235
+ /**
236
+ * Send a COM_STMT_EXECUTE
237
+ * @param out
238
+ * @param info
239
+ */
240
+ sendComStmtExecute(out, info) {
241
+ let nullCount = ~~((this.parameterCount + 7) / 8);
242
+ const nullBitsBuffer = Buffer.alloc(nullCount);
243
+ for (let i = 0; i < this.parameterCount; i++) {
244
+ if (this.values[i] == null) {
245
+ nullBitsBuffer[~~(i / 8)] |= 1 << i % 8;
246
+ }
247
+ }
248
+
249
+ out.startPacket(this);
250
+ out.writeInt8(0x17); // COM_STMT_EXECUTE
251
+ out.writeInt32(this.prepare ? this.prepare.id : -1); // Statement id
252
+ out.writeInt8(0); // no cursor flag
253
+ out.writeInt32(1); // 1 command
254
+ out.writeBuffer(nullBitsBuffer, 0, nullCount); // null buffer
255
+ out.writeInt8(1); // always send type to server
256
+
257
+ // send types
258
+ for (let i = 0; i < this.parameterCount; i++) {
259
+ out.writeInt8(this.parametersType[i].type);
260
+ out.writeInt8(0);
261
+ }
262
+
263
+ //********************************************
264
+ // send not null / not streaming values
265
+ //********************************************
266
+ for (let i = 0; i < this.parameterCount; i++) {
267
+ const parameterType = this.parametersType[i];
268
+ if (parameterType.encoder) parameterType.encoder(out, this.values[i]);
269
+ }
270
+ out.flush();
271
+ this.sending = false;
272
+ this.emit('send_end');
273
+ }
274
+
275
+ /**
276
+ * Define params events.
277
+ * Each parameter indicate that he is written to socket,
278
+ * emitting event so next stream parameter can be written.
279
+ */
280
+ registerStreamSendEvent(out, info) {
281
+ // note : Implementation use recursive calls, but stack won't get near v8 max call stack size
282
+ //since event launched for stream parameter only
283
+ this.paramWritten = function () {
284
+ if (this.longDataStep) {
285
+ for (; this.currentParam < this.parameterCount; this.currentParam++) {
286
+ if (this.parametersType[this.currentParam].isLongData()) {
287
+ const value = this.values[this.currentParam];
288
+ this.sendComStmtLongData(out, info, value);
289
+ return;
290
+ }
291
+ }
292
+ this.longDataStep = false; // all streams have been send
293
+ }
294
+
295
+ if (!this.longDataStep) {
296
+ this.sendComStmtExecute(out, info);
297
+ }
298
+ }.bind(this);
299
+ }
300
+ }
301
+
302
+ class ParameterType {
303
+ constructor(type, encoder, pipe = false, isNull = false) {
304
+ this.pipe = pipe;
305
+ this.type = type;
306
+ this.encoder = encoder;
307
+ this.isNull = isNull;
308
+ }
309
+
310
+ isLongData() {
311
+ return this.encoder === null && !this.isNull;
312
+ }
313
+ }
314
+
315
+ const NULL_PARAM_TYPE = new ParameterType(FieldType.VAR_STRING, null, false, true);
316
+ const BOOLEAN_TYPE = new ParameterType(FieldType.TINY, (out, value) => out.writeInt8(value ? 0x01 : 0x00));
317
+ const BIG_BIGINT_TYPE = new ParameterType(FieldType.NEWDECIMAL, (out, value) =>
318
+ out.writeLengthEncodedString(value.toString())
319
+ );
320
+ const BIGINT_TYPE = new ParameterType(FieldType.BIGINT, (out, value) => out.writeBigInt(value));
321
+ const INT_TYPE = new ParameterType(FieldType.INT, (out, value) => out.writeInt32(value));
322
+ const DOUBLE_TYPE = new ParameterType(FieldType.DOUBLE, (out, value) => out.writeDouble(value));
323
+ const STRING_TYPE = new ParameterType(FieldType.VAR_STRING, (out, value) => out.writeLengthEncodedString(value));
324
+ const STRING_TOSTR_TYPE = new ParameterType(FieldType.VAR_STRING, (out, value) =>
325
+ out.writeLengthEncodedString(value.toString())
326
+ );
327
+ const DATE_TYPE = new ParameterType(FieldType.DATETIME, (out, value) => out.writeBinaryDate(value));
328
+ const BLOB_TYPE = new ParameterType(FieldType.BLOB, (out, value) => out.writeLengthEncodedBuffer(value));
329
+ const LONGBLOB_TYPE = new ParameterType(FieldType.BLOB, null);
330
+ const STRING_FCT_TYPE = new ParameterType(FieldType.VAR_STRING, (out, value) =>
331
+ out.writeLengthEncodedString(String(value.toSqlString()))
332
+ );
333
+ const STREAM_TYPE = new ParameterType(FieldType.BLOB, null, true);
334
+ const STRINGIFY_TYPE = new ParameterType(FieldType.VAR_STRING, (out, value) =>
335
+ out.writeLengthEncodedString(JSON.stringify(value))
336
+ );
337
+
338
+ module.exports = Execute;