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.
- package/package.json +9 -7
- package/src/auth/storageAuthProvider.js +2 -1
- package/src/controllers/archive.js +99 -6
- package/src/controllers/auth.js +3 -1
- package/src/controllers/config.js +135 -22
- package/src/controllers/connections.js +35 -2
- package/src/controllers/databaseConnections.js +101 -2
- package/src/controllers/files.js +59 -0
- package/src/controllers/jsldata.js +9 -0
- package/src/controllers/runners.js +25 -5
- package/src/controllers/serverConnections.js +22 -2
- package/src/controllers/storage.js +341 -8
- package/src/controllers/storageDb.js +59 -1
- package/src/controllers/uploads.js +0 -46
- package/src/currentVersion.js +2 -2
- package/src/main.js +7 -1
- package/src/proc/connectProcess.js +14 -2
- package/src/proc/databaseConnectionProcess.js +70 -5
- package/src/proc/serverConnectionProcess.js +7 -1
- package/src/proc/sessionProcess.js +15 -178
- package/src/shell/archiveReader.js +3 -1
- package/src/shell/collectorWriter.js +2 -2
- package/src/shell/copyStream.js +1 -0
- package/src/shell/dataReplicator.js +96 -0
- package/src/shell/download.js +22 -6
- package/src/shell/index.js +12 -2
- package/src/shell/jsonLinesWriter.js +4 -3
- package/src/shell/queryReader.js +10 -3
- package/src/shell/unzipDirectory.js +91 -0
- package/src/shell/unzipJsonLinesData.js +60 -0
- package/src/shell/unzipJsonLinesFile.js +59 -0
- package/src/shell/zipDirectory.js +49 -0
- package/src/shell/zipJsonLinesData.js +49 -0
- package/src/utility/DatastoreProxy.js +4 -0
- package/src/utility/cloudUpgrade.js +14 -1
- package/src/utility/connectUtility.js +3 -1
- package/src/utility/crypting.js +137 -22
- package/src/utility/extractSingleFileFromZip.js +77 -0
- package/src/utility/getMapExport.js +2 -0
- package/src/utility/handleQueryStream.js +186 -0
- package/src/utility/healthStatus.js +12 -1
- package/src/utility/listZipEntries.js +41 -0
- package/src/utility/processArgs.js +5 -0
- package/src/utility/sshTunnel.js +13 -2
- package/src/utility/storageReplicatorItems.js +88 -0
- 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 {
|
|
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,
|
package/src/currentVersion.js
CHANGED
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
|
-
|
|
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', ...
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
310
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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: '
|
|
18
|
+
msgtype: 'dataResult',
|
|
19
19
|
runid: this.runid,
|
|
20
|
-
|
|
20
|
+
dataResult: { rows: this.rows, structure: this.structure },
|
|
21
21
|
});
|
|
22
22
|
callback();
|
|
23
23
|
}
|