dbgate-api-premium 6.3.2 → 6.4.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.
Files changed (46) hide show
  1. package/package.json +9 -7
  2. package/src/auth/storageAuthProvider.js +2 -1
  3. package/src/controllers/archive.js +99 -6
  4. package/src/controllers/auth.js +3 -1
  5. package/src/controllers/config.js +135 -22
  6. package/src/controllers/connections.js +35 -2
  7. package/src/controllers/databaseConnections.js +101 -2
  8. package/src/controllers/files.js +59 -0
  9. package/src/controllers/jsldata.js +9 -0
  10. package/src/controllers/runners.js +25 -5
  11. package/src/controllers/serverConnections.js +22 -2
  12. package/src/controllers/storage.js +341 -8
  13. package/src/controllers/storageDb.js +59 -1
  14. package/src/controllers/uploads.js +0 -46
  15. package/src/currentVersion.js +2 -2
  16. package/src/main.js +7 -1
  17. package/src/proc/connectProcess.js +14 -2
  18. package/src/proc/databaseConnectionProcess.js +70 -5
  19. package/src/proc/serverConnectionProcess.js +7 -1
  20. package/src/proc/sessionProcess.js +15 -178
  21. package/src/shell/archiveReader.js +3 -1
  22. package/src/shell/collectorWriter.js +2 -2
  23. package/src/shell/copyStream.js +1 -0
  24. package/src/shell/dataReplicator.js +96 -0
  25. package/src/shell/download.js +22 -6
  26. package/src/shell/index.js +12 -2
  27. package/src/shell/jsonLinesWriter.js +4 -3
  28. package/src/shell/queryReader.js +10 -3
  29. package/src/shell/unzipDirectory.js +91 -0
  30. package/src/shell/unzipJsonLinesData.js +60 -0
  31. package/src/shell/unzipJsonLinesFile.js +59 -0
  32. package/src/shell/zipDirectory.js +49 -0
  33. package/src/shell/zipJsonLinesData.js +49 -0
  34. package/src/utility/DatastoreProxy.js +4 -0
  35. package/src/utility/cloudUpgrade.js +14 -1
  36. package/src/utility/connectUtility.js +3 -1
  37. package/src/utility/crypting.js +137 -22
  38. package/src/utility/extractSingleFileFromZip.js +77 -0
  39. package/src/utility/getMapExport.js +2 -0
  40. package/src/utility/handleQueryStream.js +186 -0
  41. package/src/utility/healthStatus.js +12 -1
  42. package/src/utility/listZipEntries.js +41 -0
  43. package/src/utility/processArgs.js +5 -0
  44. package/src/utility/sshTunnel.js +13 -2
  45. package/src/utility/storageReplicatorItems.js +88 -0
  46. package/src/shell/dataDuplicator.js +0 -61
@@ -1,7 +1,13 @@
1
1
  const requireEngineDriver = require('../utility/requireEngineDriver');
2
2
  const storageModel = require('../storageModel');
3
3
  const dbgateApi = require('../shell');
4
- const { getPredefinedPermissions, getLogger, extractErrorLogData } = require('dbgate-tools');
4
+ const {
5
+ getPredefinedPermissions,
6
+ getLogger,
7
+ extractErrorLogData,
8
+ runQueryFmt,
9
+ runQueryOnDriver,
10
+ } = require('dbgate-tools');
5
11
  const _ = require('lodash');
6
12
  const logger = getLogger('storageDb');
7
13
  const { extractConnectionSslParams } = require('../utility/connectUtility');
@@ -238,10 +244,60 @@ async function storageWriteConfig(group, config) {
238
244
  }
239
245
  }
240
246
 
247
+ async function storageSaveRelationDiff(table, idColumn, valueColumn, idValue, newValueSet) {
248
+ const [conn, driver] = await getStorageConnection();
249
+ if (!conn) {
250
+ return null;
251
+ }
252
+
253
+ const oldValueSet = await storageSelectFmt(`select %i from %i where %i = %v`, valueColumn, table, idColumn, idValue);
254
+
255
+ const oldValues = oldValueSet.map(x => x[valueColumn]);
256
+
257
+ for (const added of _.difference(newValueSet, oldValues)) {
258
+ await runQueryFmt(
259
+ driver,
260
+ conn,
261
+ 'insert into %i (%i, %i) values (%v, %v)',
262
+ table,
263
+ idColumn,
264
+ valueColumn,
265
+ idValue,
266
+ added
267
+ );
268
+ }
269
+
270
+ for (const removed of _.difference(oldValues, newValueSet)) {
271
+ await runQueryFmt(
272
+ driver,
273
+ conn,
274
+ 'delete from %i where %i = %v and %i = %v',
275
+ table,
276
+ idColumn,
277
+ idValue,
278
+ valueColumn,
279
+ removed
280
+ );
281
+ }
282
+ }
283
+
241
284
  function getStorageConnectionError() {
242
285
  return storageConnectionError;
243
286
  }
244
287
 
288
+ async function selectStorageIdentity(tableName) {
289
+ const [conn, driver] = await getStorageConnection();
290
+
291
+ const resp = await runQueryOnDriver(conn, driver, dmp =>
292
+ dmp.selectScopeIdentity(
293
+ // @ts-ignore
294
+ { pureName: tableName }
295
+ )
296
+ );
297
+
298
+ return Object.entries(resp.rows[0])[0][1];
299
+ }
300
+
245
301
  module.exports = {
246
302
  getStorageConnection,
247
303
  storageSelectFmt,
@@ -254,4 +310,6 @@ module.exports = {
254
310
  storageWriteConfig,
255
311
  getStorageConnectionError,
256
312
  storageSqlCommandFmt,
313
+ storageSaveRelationDiff,
314
+ selectStorageIdentity,
257
315
  };
@@ -39,52 +39,6 @@ module.exports = {
39
39
  });
40
40
  },
41
41
 
42
- uploadDataFile_meta: {
43
- method: 'post',
44
- raw: true,
45
- },
46
- uploadDataFile(req, res) {
47
- const { data } = req.files || {};
48
-
49
- if (!data) {
50
- res.json(null);
51
- return;
52
- }
53
-
54
- if (data.name.toLowerCase().endsWith('.sql')) {
55
- logger.info(`Uploading SQL file ${data.name}, size=${data.size}`);
56
- data.mv(path.join(filesdir(), 'sql', data.name), () => {
57
- res.json({
58
- name: data.name,
59
- folder: 'sql',
60
- });
61
-
62
- socket.emitChanged(`files-changed`, { folder: 'sql' });
63
- socket.emitChanged(`all-files-changed`);
64
- });
65
- return;
66
- }
67
-
68
- res.json(null);
69
- },
70
-
71
- saveDataFile_meta: true,
72
- async saveDataFile({ filePath }) {
73
- if (filePath.toLowerCase().endsWith('.sql')) {
74
- logger.info(`Saving SQL file ${filePath}`);
75
- await fs.copyFile(filePath, path.join(filesdir(), 'sql', path.basename(filePath)));
76
-
77
- socket.emitChanged(`files-changed`, { folder: 'sql' });
78
- socket.emitChanged(`all-files-changed`);
79
- return {
80
- name: path.basename(filePath),
81
- folder: 'sql',
82
- };
83
- }
84
-
85
- return null;
86
- },
87
-
88
42
  get_meta: {
89
43
  method: 'get',
90
44
  raw: true,
@@ -1,5 +1,5 @@
1
1
 
2
2
  module.exports = {
3
- version: '6.3.2',
4
- buildTime: '2025-04-02T12:10:04.222Z'
3
+ version: '6.4.0',
4
+ buildTime: '2025-04-30T07:59:56.792Z'
5
5
  };
package/src/main.js CHANGED
@@ -38,7 +38,7 @@ const { getLogger } = require('dbgate-tools');
38
38
  const { getDefaultAuthProvider } = require('./auth/authProvider');
39
39
  const startCloudUpgradeTimer = require('./utility/cloudUpgrade');
40
40
  const { isProApp } = require('./utility/checkLicense');
41
- const getHealthStatus = require('./utility/healthStatus');
41
+ const { getHealthStatus, getHealthStatusSprinx } = require('./utility/healthStatus');
42
42
 
43
43
  const logger = getLogger('main');
44
44
 
@@ -124,6 +124,12 @@ function start() {
124
124
  res.end(JSON.stringify(health, null, 2));
125
125
  });
126
126
 
127
+ app.get(getExpressPath('/__health'), async function (req, res) {
128
+ res.setHeader('Content-Type', 'application/json');
129
+ const health = await getHealthStatusSprinx();
130
+ res.end(JSON.stringify(health, null, 2));
131
+ });
132
+
127
133
  app.use(bodyParser.json({ limit: '50mb' }));
128
134
 
129
135
  app.use(
@@ -4,6 +4,8 @@ const { connectUtility } = require('../utility/connectUtility');
4
4
  const { handleProcessCommunication } = require('../utility/processComm');
5
5
  const { pickSafeConnectionInfo } = require('../utility/crypting');
6
6
  const _ = require('lodash');
7
+ const { getLogger, extractErrorLogData } = require('dbgate-tools');
8
+ const logger = getLogger('connectProcess');
7
9
 
8
10
  const formatErrorDetail = (e, connection) => `${e.stack}
9
11
 
@@ -23,12 +25,22 @@ function start() {
23
25
  try {
24
26
  const driver = requireEngineDriver(connection);
25
27
  const dbhan = await connectUtility(driver, connection, 'app');
26
- const res = await driver.getVersion(dbhan);
28
+ let version = {
29
+ version: 'Unknown',
30
+ };
31
+ try {
32
+ version = await driver.getVersion(dbhan);
33
+ } catch (err) {
34
+ logger.error(extractErrorLogData(err), 'Error getting DB server version');
35
+ version = {
36
+ version: 'Unknown',
37
+ };
38
+ }
27
39
  let databases = undefined;
28
40
  if (requestDbList) {
29
41
  databases = await driver.listDatabases(dbhan);
30
42
  }
31
- process.send({ msgtype: 'connected', ...res, databases });
43
+ process.send({ msgtype: 'connected', ...version, databases });
32
44
  await driver.close(dbhan);
33
45
  } catch (e) {
34
46
  console.error(e);
@@ -9,13 +9,21 @@ const {
9
9
  dbNameLogCategory,
10
10
  extractErrorMessage,
11
11
  extractErrorLogData,
12
+ ScriptWriterEval,
13
+ SqlGenerator,
14
+ playJsonScriptWriter,
12
15
  } = require('dbgate-tools');
13
16
  const requireEngineDriver = require('../utility/requireEngineDriver');
14
17
  const { connectUtility } = require('../utility/connectUtility');
15
18
  const { handleProcessCommunication } = require('../utility/processComm');
16
- const { SqlGenerator } = require('dbgate-tools');
17
19
  const generateDeploySql = require('../shell/generateDeploySql');
18
20
  const { dumpSqlSelect } = require('dbgate-sqltree');
21
+ const { allowExecuteCustomScript, handleQueryStream } = require('../utility/handleQueryStream');
22
+ const dbgateApi = require('../shell');
23
+ const requirePlugin = require('../shell/requirePlugin');
24
+ const path = require('path');
25
+ const { rundir } = require('../utility/directories');
26
+ const fs = require('fs-extra');
19
27
 
20
28
  const logger = getLogger('dbconnProcess');
21
29
 
@@ -120,10 +128,15 @@ function setStatusName(name) {
120
128
 
121
129
  async function readVersion() {
122
130
  const driver = requireEngineDriver(storedConnection);
123
- const version = await driver.getVersion(dbhan);
124
- logger.debug(`Got server version: ${version.version}`);
125
- process.send({ msgtype: 'version', version });
126
- serverVersion = version;
131
+ try {
132
+ const version = await driver.getVersion(dbhan);
133
+ logger.debug(`Got server version: ${version.version}`);
134
+ serverVersion = version;
135
+ } catch (err) {
136
+ logger.error(extractErrorLogData(err), 'Error getting DB server version');
137
+ serverVersion = { version: 'Unknown' };
138
+ }
139
+ process.send({ msgtype: 'version', version: serverVersion });
127
140
  }
128
141
 
129
142
  async function handleConnect({ connection, structure, globalSettings }) {
@@ -370,6 +383,56 @@ async function handleGenerateDeploySql({ msgid, modelFolder }) {
370
383
  }
371
384
  }
372
385
 
386
+ async function handleExecuteSessionQuery({ sesid, sql }) {
387
+ await waitConnected();
388
+ const driver = requireEngineDriver(storedConnection);
389
+
390
+ if (!allowExecuteCustomScript(storedConnection, driver)) {
391
+ process.send({
392
+ msgtype: 'info',
393
+ info: {
394
+ message: 'Connection without read-only sessions is read only',
395
+ severity: 'error',
396
+ },
397
+ sesid,
398
+ });
399
+ process.send({ msgtype: 'done', sesid, skipFinishedMessage: true });
400
+ return;
401
+ //process.send({ msgtype: 'error', error: e.message });
402
+ }
403
+
404
+ const queryStreamInfoHolder = {
405
+ resultIndex: 0,
406
+ canceled: false,
407
+ };
408
+ for (const sqlItem of splitQuery(sql, {
409
+ ...driver.getQuerySplitterOptions('stream'),
410
+ returnRichInfo: true,
411
+ })) {
412
+ await handleQueryStream(dbhan, driver, queryStreamInfoHolder, sqlItem, sesid);
413
+ if (queryStreamInfoHolder.canceled) {
414
+ break;
415
+ }
416
+ }
417
+ process.send({ msgtype: 'done', sesid });
418
+ }
419
+
420
+ async function handleEvalJsonScript({ script, runid }) {
421
+ const directory = path.join(rundir(), runid);
422
+ fs.mkdirSync(directory);
423
+ const originalCwd = process.cwd();
424
+
425
+ try {
426
+ process.chdir(directory);
427
+
428
+ const evalWriter = new ScriptWriterEval(dbgateApi, requirePlugin, dbhan, runid);
429
+ await playJsonScriptWriter(script, evalWriter);
430
+ process.send({ msgtype: 'runnerDone', runid });
431
+ } finally {
432
+ process.chdir(originalCwd);
433
+ }
434
+ }
435
+
373
436
  // async function handleRunCommand({ msgid, sql }) {
374
437
  // await waitConnected();
375
438
  // const driver = engines(storedConnection);
@@ -400,6 +463,8 @@ const messageHandlers = {
400
463
  sqlSelect: handleSqlSelect,
401
464
  exportKeys: handleExportKeys,
402
465
  schemaList: handleSchemaList,
466
+ executeSessionQuery: handleExecuteSessionQuery,
467
+ evalJsonScript: handleEvalJsonScript,
403
468
  // runCommand: handleRunCommand,
404
469
  };
405
470
 
@@ -46,7 +46,13 @@ async function handleRefresh() {
46
46
 
47
47
  async function readVersion() {
48
48
  const driver = requireEngineDriver(storedConnection);
49
- const version = await driver.getVersion(dbhan);
49
+ let version;
50
+ try {
51
+ version = await driver.getVersion(dbhan);
52
+ } catch (err) {
53
+ logger.error(extractErrorLogData(err), 'Error getting DB server version');
54
+ version = { version: 'Unknown' };
55
+ }
50
56
  process.send({ msgtype: 'version', version });
51
57
  }
52
58
 
@@ -11,6 +11,7 @@ const { decryptConnection } = require('../utility/crypting');
11
11
  const { connectUtility } = require('../utility/connectUtility');
12
12
  const { handleProcessCommunication } = require('../utility/processComm');
13
13
  const { getLogger, extractIntSettingsValue, extractBoolSettingsValue } = require('dbgate-tools');
14
+ const { handleQueryStream, QueryStreamTableWriter, allowExecuteCustomScript } = require('../utility/handleQueryStream');
14
15
 
15
16
  const logger = getLogger('sessionProcess');
16
17
 
@@ -23,175 +24,6 @@ let lastActivity = null;
23
24
  let currentProfiler = null;
24
25
  let executingScripts = 0;
25
26
 
26
- class TableWriter {
27
- constructor() {
28
- this.currentRowCount = 0;
29
- this.currentChangeIndex = 1;
30
- this.initializedFile = false;
31
- }
32
-
33
- initializeFromQuery(structure, resultIndex) {
34
- this.jslid = crypto.randomUUID();
35
- this.currentFile = path.join(jsldir(), `${this.jslid}.jsonl`);
36
- fs.writeFileSync(
37
- this.currentFile,
38
- JSON.stringify({
39
- ...structure,
40
- __isStreamHeader: true,
41
- }) + '\n'
42
- );
43
- this.currentStream = fs.createWriteStream(this.currentFile, { flags: 'a' });
44
- this.writeCurrentStats(false, false);
45
- this.resultIndex = resultIndex;
46
- this.initializedFile = true;
47
- process.send({ msgtype: 'recordset', jslid: this.jslid, resultIndex });
48
- }
49
-
50
- initializeFromReader(jslid) {
51
- this.jslid = jslid;
52
- this.currentFile = path.join(jsldir(), `${this.jslid}.jsonl`);
53
- this.writeCurrentStats(false, false);
54
- }
55
-
56
- row(row) {
57
- // console.log('ACCEPT ROW', row);
58
- this.currentStream.write(JSON.stringify(row) + '\n');
59
- this.currentRowCount += 1;
60
-
61
- if (!this.plannedStats) {
62
- this.plannedStats = true;
63
- process.nextTick(() => {
64
- if (this.currentStream) this.currentStream.uncork();
65
- process.nextTick(() => this.writeCurrentStats(false, true));
66
- this.plannedStats = false;
67
- });
68
- }
69
- }
70
-
71
- rowFromReader(row) {
72
- if (!this.initializedFile) {
73
- process.send({ msgtype: 'initializeFile', jslid: this.jslid });
74
- this.initializedFile = true;
75
-
76
- fs.writeFileSync(this.currentFile, JSON.stringify(row) + '\n');
77
- this.currentStream = fs.createWriteStream(this.currentFile, { flags: 'a' });
78
- this.writeCurrentStats(false, false);
79
- this.initializedFile = true;
80
- return;
81
- }
82
-
83
- this.row(row);
84
- }
85
-
86
- writeCurrentStats(isFinished = false, emitEvent = false) {
87
- const stats = {
88
- rowCount: this.currentRowCount,
89
- changeIndex: this.currentChangeIndex,
90
- isFinished,
91
- jslid: this.jslid,
92
- };
93
- fs.writeFileSync(`${this.currentFile}.stats`, JSON.stringify(stats));
94
- this.currentChangeIndex += 1;
95
- if (emitEvent) {
96
- process.send({ msgtype: 'stats', ...stats });
97
- }
98
- }
99
-
100
- close(afterClose) {
101
- if (this.currentStream) {
102
- this.currentStream.end(() => {
103
- this.writeCurrentStats(true, true);
104
- if (afterClose) afterClose();
105
- });
106
- }
107
- }
108
- }
109
-
110
- class StreamHandler {
111
- constructor(resultIndexHolder, resolve, startLine) {
112
- this.recordset = this.recordset.bind(this);
113
- this.startLine = startLine;
114
- this.row = this.row.bind(this);
115
- // this.error = this.error.bind(this);
116
- this.done = this.done.bind(this);
117
- this.info = this.info.bind(this);
118
-
119
- // use this for cancelling - not implemented
120
- // this.stream = null;
121
-
122
- this.plannedStats = false;
123
- this.resultIndexHolder = resultIndexHolder;
124
- this.resolve = resolve;
125
- // currentHandlers = [...currentHandlers, this];
126
- }
127
-
128
- closeCurrentWriter() {
129
- if (this.currentWriter) {
130
- this.currentWriter.close();
131
- this.currentWriter = null;
132
- }
133
- }
134
-
135
- recordset(columns) {
136
- this.closeCurrentWriter();
137
- this.currentWriter = new TableWriter();
138
- this.currentWriter.initializeFromQuery(
139
- Array.isArray(columns) ? { columns } : columns,
140
- this.resultIndexHolder.value
141
- );
142
- this.resultIndexHolder.value += 1;
143
-
144
- // this.writeCurrentStats();
145
-
146
- // this.onRow = _.throttle((jslid) => {
147
- // if (jslid == this.jslid) {
148
- // this.writeCurrentStats(false, true);
149
- // }
150
- // }, 500);
151
- }
152
- row(row) {
153
- if (this.currentWriter) this.currentWriter.row(row);
154
- else if (row.message) process.send({ msgtype: 'info', info: { message: row.message } });
155
- // this.onRow(this.jslid);
156
- }
157
- // error(error) {
158
- // process.send({ msgtype: 'error', error });
159
- // }
160
- done(result) {
161
- this.closeCurrentWriter();
162
- // currentHandlers = currentHandlers.filter((x) => x != this);
163
- this.resolve();
164
- }
165
- info(info) {
166
- if (info && info.line != null) {
167
- info = {
168
- ...info,
169
- line: this.startLine + info.line,
170
- };
171
- }
172
- process.send({ msgtype: 'info', info });
173
- }
174
- }
175
-
176
- function handleStream(driver, resultIndexHolder, sqlItem) {
177
- return new Promise((resolve, reject) => {
178
- const start = sqlItem.trimStart || sqlItem.start;
179
- const handler = new StreamHandler(resultIndexHolder, resolve, start && start.line);
180
- driver.stream(dbhan, sqlItem.text, handler);
181
- });
182
- }
183
-
184
- function allowExecuteCustomScript(driver) {
185
- if (driver.readOnlySessions) {
186
- return true;
187
- }
188
- if (storedConnection.isReadOnly) {
189
- return false;
190
- // throw new Error('Connection is read only');
191
- }
192
- return true;
193
- }
194
-
195
27
  async function handleConnect(connection) {
196
28
  storedConnection = connection;
197
29
 
@@ -222,12 +54,12 @@ async function handleStartProfiler({ jslid }) {
222
54
  await waitConnected();
223
55
  const driver = requireEngineDriver(storedConnection);
224
56
 
225
- if (!allowExecuteCustomScript(driver)) {
57
+ if (!allowExecuteCustomScript(storedConnection, driver)) {
226
58
  process.send({ msgtype: 'done' });
227
59
  return;
228
60
  }
229
61
 
230
- const writer = new TableWriter();
62
+ const writer = new QueryStreamTableWriter();
231
63
  writer.initializeFromReader(jslid);
232
64
 
233
65
  currentProfiler = await driver.startProfiler(dbhan, {
@@ -251,7 +83,7 @@ async function handleExecuteControlCommand({ command }) {
251
83
  await waitConnected();
252
84
  const driver = requireEngineDriver(storedConnection);
253
85
 
254
- if (command == 'commitTransaction' && !allowExecuteCustomScript(driver)) {
86
+ if (command == 'commitTransaction' && !allowExecuteCustomScript(storedConnection, driver)) {
255
87
  process.send({
256
88
  msgtype: 'info',
257
89
  info: {
@@ -291,7 +123,7 @@ async function handleExecuteQuery({ sql, autoCommit }) {
291
123
  await waitConnected();
292
124
  const driver = requireEngineDriver(storedConnection);
293
125
 
294
- if (!allowExecuteCustomScript(driver)) {
126
+ if (!allowExecuteCustomScript(storedConnection, driver)) {
295
127
  process.send({
296
128
  msgtype: 'info',
297
129
  info: {
@@ -306,18 +138,23 @@ async function handleExecuteQuery({ sql, autoCommit }) {
306
138
 
307
139
  executingScripts++;
308
140
  try {
309
- const resultIndexHolder = {
310
- value: 0,
141
+ const queryStreamInfoHolder = {
142
+ resultIndex: 0,
143
+ canceled: false,
311
144
  };
312
145
  for (const sqlItem of splitQuery(sql, {
313
146
  ...driver.getQuerySplitterOptions('stream'),
314
147
  returnRichInfo: true,
315
148
  })) {
316
- await handleStream(driver, resultIndexHolder, sqlItem);
149
+ await handleQueryStream(dbhan, driver, queryStreamInfoHolder, sqlItem);
317
150
  // const handler = new StreamHandler(resultIndex);
318
151
  // const stream = await driver.stream(systemConnection, sqlItem, handler);
319
152
  // handler.stream = stream;
320
153
  // resultIndex = handler.resultIndex;
154
+
155
+ if (queryStreamInfoHolder.canceled) {
156
+ break;
157
+ }
321
158
  }
322
159
  process.send({ msgtype: 'done', autoCommit });
323
160
  } finally {
@@ -335,13 +172,13 @@ async function handleExecuteReader({ jslid, sql, fileName }) {
335
172
  if (fileName) {
336
173
  sql = fs.readFileSync(fileName, 'utf-8');
337
174
  } else {
338
- if (!allowExecuteCustomScript(driver)) {
175
+ if (!allowExecuteCustomScript(storedConnection, driver)) {
339
176
  process.send({ msgtype: 'done' });
340
177
  return;
341
178
  }
342
179
  }
343
180
 
344
- const writer = new TableWriter();
181
+ const writer = new QueryStreamTableWriter();
345
182
  writer.initializeFromReader(jslid);
346
183
 
347
184
  const reader = await driver.readQuery(dbhan, sql);
@@ -3,7 +3,9 @@ const { archivedir, resolveArchiveFolder } = require('../utility/directories');
3
3
  const jsonLinesReader = require('./jsonLinesReader');
4
4
 
5
5
  function archiveReader({ folderName, fileName, ...other }) {
6
- const jsonlFile = path.join(resolveArchiveFolder(folderName), `${fileName}.jsonl`);
6
+ const jsonlFile = folderName.endsWith('.zip')
7
+ ? `zip://archive:${folderName}//${fileName}.jsonl`
8
+ : path.join(resolveArchiveFolder(folderName), `${fileName}.jsonl`);
7
9
  const res = jsonLinesReader({ fileName: jsonlFile, ...other });
8
10
  return res;
9
11
  }
@@ -15,9 +15,9 @@ class CollectorWriterStream extends stream.Writable {
15
15
 
16
16
  _final(callback) {
17
17
  process.send({
18
- msgtype: 'freeData',
18
+ msgtype: 'dataResult',
19
19
  runid: this.runid,
20
- freeData: { rows: this.rows, structure: this.structure },
20
+ dataResult: { rows: this.rows, structure: this.structure },
21
21
  });
22
22
  callback();
23
23
  }
@@ -69,6 +69,7 @@ async function copyStream(input, output, options) {
69
69
  msgtype: 'copyStreamError',
70
70
  copyStreamError: {
71
71
  message: extractErrorMessage(err),
72
+ progressName,
72
73
  ...err,
73
74
  },
74
75
  });