dbgate-api-premium 6.1.6 → 6.2.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dbgate-api-premium",
3
3
  "main": "src/index.js",
4
- "version": "6.1.6",
4
+ "version": "6.2.1",
5
5
  "homepage": "https://dbgate.org/",
6
6
  "repository": {
7
7
  "type": "git",
@@ -29,10 +29,10 @@
29
29
  "compare-versions": "^3.6.0",
30
30
  "cors": "^2.8.5",
31
31
  "cross-env": "^6.0.3",
32
- "dbgate-datalib": "^6.1.6",
32
+ "dbgate-datalib": "^6.2.1",
33
33
  "dbgate-query-splitter": "^4.11.3",
34
- "dbgate-sqltree": "^6.1.6",
35
- "dbgate-tools": "^6.1.6",
34
+ "dbgate-sqltree": "^6.2.1",
35
+ "dbgate-tools": "^6.2.1",
36
36
  "debug": "^4.3.4",
37
37
  "diff": "^5.0.0",
38
38
  "diff2html": "^3.4.13",
@@ -74,6 +74,8 @@
74
74
  "start:storage": "env-cmd -f env/storage/.env node src/index.js --listen-api",
75
75
  "start:storage:built": "env-cmd -f env/storage/.env cross-env DEVMODE= BUILTWEBMODE=1 node dist/bundle.js --listen-api",
76
76
  "start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api",
77
+ "start:azure": "env-cmd -f env/azure/.env node src/index.js --listen-api",
78
+ "start:e2e:team": "cross-env DEVWEB=1 DEVMODE=1 env-cmd -f ../../e2e-tests/env/team/.env node src/index.js --listen-api",
77
79
  "ts": "tsc",
78
80
  "build": "webpack",
79
81
  "build:doc": "jsdoc2md --template doctpl.hbs ./src/shell/* > ../../../dbgate.github.io/_docs/apidoc.md"
@@ -81,7 +83,7 @@
81
83
  "devDependencies": {
82
84
  "@types/fs-extra": "^9.0.11",
83
85
  "@types/lodash": "^4.14.149",
84
- "dbgate-types": "^6.1.6",
86
+ "dbgate-types": "^6.2.1",
85
87
  "env-cmd": "^10.1.0",
86
88
  "jsdoc-to-markdown": "^9.0.5",
87
89
  "node-loader": "^1.0.2",
@@ -3,12 +3,14 @@ const {
3
3
  getPredefinedPermissions,
4
4
  getLogger,
5
5
  getConnectionLabel,
6
+ runQueryFmt,
6
7
  } = require('dbgate-tools');
7
8
  const {
8
9
  storageSelectFmt,
9
10
  storageReadUserRolePermissions,
10
11
  storageReadUserPermissions,
11
12
  storageReadRolePermissions,
13
+ storageSqlCommandFmt,
12
14
  } = require('../controllers/storageDb');
13
15
  const { getTokenSecret, getTokenLifetime } = require('./authCommon');
14
16
  const { AuthProviderBase } = require('./authProvider');
@@ -129,9 +131,13 @@ class OauthProvider extends StorageProviderBase {
129
131
  )}&client_id=${this.config.oauthClient}&client_secret=${this.config.oauthClientSecret}${scopeParam}`
130
132
  );
131
133
 
132
- const { access_token, refresh_token } = resp.data;
134
+ const { access_token, id_token, refresh_token } = resp.data;
133
135
 
134
- const payload = jwt.decode(access_token);
136
+ if (!id_token && !access_token) {
137
+ return { error: 'Token not found' };
138
+ }
139
+
140
+ const payload = jwt.decode(id_token ?? access_token);
135
141
 
136
142
  logger.info({ payload }, 'User payload returned from OAUTH');
137
143
 
@@ -143,10 +149,13 @@ class OauthProvider extends StorageProviderBase {
143
149
  const loginRows = await storageSelectFmt('select * from ~users where ~login = %v', login);
144
150
  const permissions = await loadPermissionsForUserId(loginRows[0]?.id ?? -1);
145
151
 
146
- if (this.config.oauthOnlyDefinedLogins == 1) {
147
- if (loginRows.length == 0) {
148
- return { error: `Username ${login} not allowed to log in` };
149
- }
152
+ if (this.config.oauthOnlyDefinedLogins == 1 && loginRows.length == 0) {
153
+ return { error: `Username ${login} not allowed to log in` };
154
+ }
155
+
156
+ if (this.config.oauthSaveNotDefinedLogins == 1 && loginRows.length == 0) {
157
+ const email = payload[this.config.oauthEmailField || 'email'] ?? null;
158
+ await storageSqlCommandFmt('insert into ~users (~login, ~email) values (%v, %v)', login, email);
150
159
  }
151
160
 
152
161
  let groups =
@@ -165,22 +174,18 @@ class OauthProvider extends StorageProviderBase {
165
174
  }
166
175
  }
167
176
 
168
- if (access_token) {
169
- return {
170
- accessToken: jwt.sign(
171
- {
172
- amoid: this.amoid,
173
- login,
174
- permissions,
175
- userId: loginRows[0]?.id,
176
- },
177
- getTokenSecret(),
178
- { expiresIn: getTokenLifetime() }
179
- ),
180
- };
181
- }
182
-
183
- return { error: 'Token not found' };
177
+ return {
178
+ accessToken: jwt.sign(
179
+ {
180
+ amoid: this.amoid,
181
+ login,
182
+ permissions,
183
+ userId: loginRows[0]?.id,
184
+ },
185
+ getTokenSecret(),
186
+ { expiresIn: getTokenLifetime() }
187
+ ),
188
+ };
184
189
  }
185
190
 
186
191
  redirect({ state, redirectUri }) {
@@ -136,7 +136,7 @@ module.exports = {
136
136
 
137
137
  deleteSettings_meta: true,
138
138
  async deleteSettings() {
139
- await fs.unlink(path.join(datadir(), 'settings.json'));
139
+ await fs.unlink(path.join(datadir(), processArgs.runE2eTests ? 'settings-e2etests.json' : 'settings.json'));
140
140
  return true;
141
141
  },
142
142
 
@@ -161,7 +161,10 @@ module.exports = {
161
161
 
162
162
  async loadSettings() {
163
163
  try {
164
- const settingsText = await fs.readFile(path.join(datadir(), 'settings.json'), { encoding: 'utf-8' });
164
+ const settingsText = await fs.readFile(
165
+ path.join(datadir(), processArgs.runE2eTests ? 'settings-e2etests.json' : 'settings.json'),
166
+ { encoding: 'utf-8' }
167
+ );
165
168
  return {
166
169
  ...this.fillMissingSettings(JSON.parse(settingsText)),
167
170
  'other.licenseKey': platformInfo.isElectron ? await this.loadLicenseKey() : undefined,
@@ -247,7 +250,10 @@ module.exports = {
247
250
  ...currentValue,
248
251
  ..._.omit(values, ['other.licenseKey']),
249
252
  };
250
- await fs.writeFile(path.join(datadir(), 'settings.json'), JSON.stringify(updated, undefined, 2));
253
+ await fs.writeFile(
254
+ path.join(datadir(), processArgs.runE2eTests ? 'settings-e2etests.json' : 'settings.json'),
255
+ JSON.stringify(updated, undefined, 2)
256
+ );
251
257
  // this.settingsValue = updated;
252
258
 
253
259
  if (currentValue['other.licenseKey'] != values['other.licenseKey']) {
@@ -34,6 +34,8 @@ const pipeForkLogs = require('../utility/pipeForkLogs');
34
34
  const crypto = require('crypto');
35
35
  const loadModelTransform = require('../utility/loadModelTransform');
36
36
  const exportDbModelSql = require('../utility/exportDbModelSql');
37
+ const axios = require('axios');
38
+ const { callTextToSqlApi, callCompleteOnCursorApi, callRefactorSqlQueryApi } = require('../utility/authProxy');
37
39
 
38
40
  const logger = getLogger('databaseConnections');
39
41
 
@@ -69,6 +71,11 @@ module.exports = {
69
71
  handle_error(conid, database, props) {
70
72
  const { error } = props;
71
73
  logger.error(`Error in database connection ${conid}, database ${database}: ${error}`);
74
+ if (props?.msgid) {
75
+ const [resolve, reject] = this.requests[props?.msgid];
76
+ reject(error);
77
+ delete this.requests[props?.msgid];
78
+ }
72
79
  },
73
80
  handle_response(conid, database, { msgid, ...response }) {
74
81
  const [resolve, reject] = this.requests[msgid];
@@ -253,9 +260,9 @@ module.exports = {
253
260
  },
254
261
 
255
262
  loadFieldValues_meta: true,
256
- async loadFieldValues({ conid, database, schemaName, pureName, field, search }, req) {
263
+ async loadFieldValues({ conid, database, schemaName, pureName, field, search, dataType }, req) {
257
264
  testConnectionPermission(conid, req);
258
- return this.loadDataCore('loadFieldValues', { conid, database, schemaName, pureName, field, search });
265
+ return this.loadDataCore('loadFieldValues', { conid, database, schemaName, pureName, field, search, dataType });
259
266
  },
260
267
 
261
268
  callMethod_meta: true,
@@ -401,6 +408,10 @@ module.exports = {
401
408
 
402
409
  structure_meta: true,
403
410
  async structure({ conid, database, modelTransFile = null }, req) {
411
+ if (!conid || !database) {
412
+ return {};
413
+ }
414
+
404
415
  testConnectionPermission(conid, req);
405
416
  if (conid == '__model') {
406
417
  const model = await importDbModel(database);
@@ -558,4 +569,47 @@ module.exports = {
558
569
 
559
570
  return true;
560
571
  },
572
+
573
+ textToSql_meta: true,
574
+ async textToSql({ conid, database, text, dialect }) {
575
+ const existing = this.opened.find(x => x.conid == conid && x.database == database);
576
+ const { structure } = existing || {};
577
+ if (!structure) return { errorMessage: 'No database structure' };
578
+
579
+ const res = await callTextToSqlApi(text, structure, dialect);
580
+
581
+ if (!res?.sql) {
582
+ return { errorMessage: 'No SQL generated' };
583
+ }
584
+
585
+ return res;
586
+ },
587
+
588
+ completeOnCursor_meta: true,
589
+ async completeOnCursor({ conid, database, text, dialect, line }) {
590
+ const existing = this.opened.find(x => x.conid == conid && x.database == database);
591
+ const { structure } = existing || {};
592
+ if (!structure) return { errorMessage: 'No database structure' };
593
+ const res = await callCompleteOnCursorApi(text, structure, dialect, line);
594
+
595
+ if (!res?.variants) {
596
+ return { errorMessage: 'No SQL generated' };
597
+ }
598
+
599
+ return res;
600
+ },
601
+
602
+ refactorSqlQuery_meta: true,
603
+ async refactorSqlQuery({ conid, database, query, task, dialect }) {
604
+ const existing = this.opened.find(x => x.conid == conid && x.database == database);
605
+ const { structure } = existing || {};
606
+ if (!structure) return { errorMessage: 'No database structure' };
607
+ const res = await callRefactorSqlQueryApi(query, task, structure, dialect);
608
+
609
+ if (!res?.sql) {
610
+ return { errorMessage: 'No SQL generated' };
611
+ }
612
+
613
+ return res;
614
+ },
561
615
  };
@@ -56,12 +56,19 @@ module.exports = {
56
56
  handle_done(sesid, props) {
57
57
  socket.emit(`session-done-${sesid}`);
58
58
  if (!props.skipFinishedMessage) {
59
- this.dispatchMessage(sesid, 'Query execution finished');
59
+ if (props.controlCommand) {
60
+ this.dispatchMessage(sesid, `${_.startCase(props.controlCommand)} finished`);
61
+ } else {
62
+ this.dispatchMessage(sesid, 'Query execution finished');
63
+ }
60
64
  }
61
65
  const session = this.opened.find(x => x.sesid == sesid);
62
66
  if (session.loadingReader_jslid) {
63
67
  socket.emit(`session-jslid-done-${session.loadingReader_jslid}`);
64
68
  }
69
+ if (props.autoCommit) {
70
+ this.executeControlCommand({ sesid, command: 'commitTransaction' });
71
+ }
65
72
  if (session.killOnDone) {
66
73
  this.kill({ sesid });
67
74
  }
@@ -131,7 +138,7 @@ module.exports = {
131
138
  },
132
139
 
133
140
  executeQuery_meta: true,
134
- async executeQuery({ sesid, sql }) {
141
+ async executeQuery({ sesid, sql, autoCommit }) {
135
142
  const session = this.opened.find(x => x.sesid == sesid);
136
143
  if (!session) {
137
144
  throw new Error('Invalid session');
@@ -139,7 +146,21 @@ module.exports = {
139
146
 
140
147
  logger.info({ sesid, sql }, 'Processing query');
141
148
  this.dispatchMessage(sesid, 'Query execution started');
142
- session.subprocess.send({ msgtype: 'executeQuery', sql });
149
+ session.subprocess.send({ msgtype: 'executeQuery', sql, autoCommit });
150
+
151
+ return { state: 'ok' };
152
+ },
153
+
154
+ executeControlCommand_meta: true,
155
+ async executeControlCommand({ sesid, command }) {
156
+ const session = this.opened.find(x => x.sesid == sesid);
157
+ if (!session) {
158
+ throw new Error('Invalid session');
159
+ }
160
+
161
+ logger.info({ sesid, command }, 'Processing control command');
162
+ this.dispatchMessage(sesid, `${_.startCase(command)} started`);
163
+ session.subprocess.send({ msgtype: 'executeControlCommand', command });
143
164
 
144
165
  return { state: 'ok' };
145
166
  },
@@ -17,7 +17,7 @@ const { hasPermission } = require('../utility/hasPermission');
17
17
  const { changeSetToSql, removeSchemaFromChangeSet } = require('dbgate-datalib');
18
18
  const storageModel = require('../storageModel');
19
19
  const { dumpSqlCommand } = require('dbgate-sqltree');
20
- const { runCommandOnDriver, getLogger } = require('dbgate-tools');
20
+ const { runCommandOnDriver, getLogger, runQueryFmt } = require('dbgate-tools');
21
21
  const socket = require('../utility/socket');
22
22
  const { obtainRefreshedLicense } = require('../utility/authProxy');
23
23
  const { datadir } = require('../utility/directories');
@@ -31,11 +31,6 @@ function mapConnection(connnection) {
31
31
  };
32
32
  }
33
33
 
34
- async function runQueryFmt(driver, conn, query, ...args) {
35
- const dmp = driver.createDumper();
36
- dmp.put(query, ...args);
37
- await driver.query(conn, dmp.s);
38
- }
39
34
 
40
35
  let refreshLicenseStarted = false;
41
36
 
@@ -140,7 +135,7 @@ module.exports = {
140
135
  displayName: 'Internal storage',
141
136
  defaultDatabase: process.env.STORAGE_DATABASE,
142
137
  singleDatabase: true,
143
- ...getDbConnectionParams(),
138
+ ...await getDbConnectionParams(),
144
139
  };
145
140
  }
146
141
 
@@ -197,7 +192,8 @@ module.exports = {
197
192
  await runQueryFmt(
198
193
  driver,
199
194
  conn,
200
- 'update auth_methods set is_disabled=%v, is_default = %v, is_collapsed = %v where id = %v',
195
+ 'update auth_methods set name=%v, is_disabled=%v, is_default = %v, is_collapsed = %v where id = %v',
196
+ method.name,
201
197
  method.isDisabled,
202
198
  method.isDefault,
203
199
  method.isCollapsed,
@@ -4,8 +4,9 @@ const dbgateApi = require('../shell');
4
4
  const { getPredefinedPermissions, getLogger, extractErrorLogData } = require('dbgate-tools');
5
5
  const _ = require('lodash');
6
6
  const logger = getLogger('storageDb');
7
+ const { extractConnectionSslParams } = require('../utility/connectUtility');
7
8
 
8
- function getDbConnectionParams() {
9
+ async function getDbConnectionParams() {
9
10
  const server = process.env.STORAGE_SERVER;
10
11
  const port = process.env.STORAGE_PORT;
11
12
  const user = process.env.STORAGE_USER;
@@ -13,21 +14,33 @@ function getDbConnectionParams() {
13
14
  const database = process.env.STORAGE_DATABASE;
14
15
  const engine = process.env.STORAGE_ENGINE;
15
16
  const serviceName = process.env.STORAGE_SERVICE_NAME;
17
+ const socketPath = process.env.STORAGE_SOCKET_PATH;
18
+ const databaseUrl = process.env.STORAGE_DATABASE_URL;
19
+ const useDatabaseUrl = !!process.env.STORAGE_DATABASE_URL;
20
+ const authType = process.env.STORAGE_AUTH_TYPE;
16
21
 
17
- if (!server || !user || !password || !database || !engine) {
22
+ const useSsl = process.env.STORAGE_USE_SSL;
23
+ const sslCaFile = process.env.STORAGE_SSL_CA_FILE;
24
+ const sslCertFile = process.env.STORAGE_SSL_CERT_FILE;
25
+ const sslCertFilePassword = process.env.STORAGE_SSL_CERT_FILE_PASSWORD;
26
+ const sslKeyFile = process.env.STORAGE_SSL_KEY_FILE;
27
+ const sslRejectUnauthorized = process.env.STORAGE_SSL_REJECT_UNAUTHORIZED;
28
+ const trustServerCertificate = process.env.STORAGE_SSL_TRUST_CERTIFICATE;
29
+
30
+ if (!server || !engine) {
18
31
  if (database) {
19
32
  if (!server) {
20
33
  throw new Error('Incorrect storage configuration, missing env variable STORAGE_SERVER');
21
34
  }
22
- if (!port) {
23
- throw new Error('Incorrect storage configuration, missing env variable STORAGE_PORT');
24
- }
25
- if (!user) {
26
- throw new Error('Incorrect storage configuration, missing env variable STORAGE_USER');
27
- }
28
- if (!password) {
29
- throw new Error('Incorrect storage configuration, missing env variable STORAGE_PASSWORD');
30
- }
35
+ // if (!port) {
36
+ // throw new Error('Incorrect storage configuration, missing env variable STORAGE_PORT');
37
+ // }
38
+ // if (!user) {
39
+ // throw new Error('Incorrect storage configuration, missing env variable STORAGE_USER');
40
+ // }
41
+ // if (!password) {
42
+ // throw new Error('Incorrect storage configuration, missing env variable STORAGE_PASSWORD');
43
+ // }
31
44
  if (!engine) {
32
45
  throw new Error('Incorrect storage configuration, missing env variable STORAGE_ENGINE');
33
46
  }
@@ -35,7 +48,30 @@ function getDbConnectionParams() {
35
48
  return null;
36
49
  }
37
50
 
38
- return { server, port, user, password, database, engine, serviceName };
51
+ const res = {
52
+ server,
53
+ port,
54
+ user,
55
+ password,
56
+ database,
57
+ engine,
58
+ serviceName,
59
+ socketPath,
60
+ databaseUrl,
61
+ useDatabaseUrl,
62
+ authType,
63
+ useSsl,
64
+ sslCaFile,
65
+ sslCertFile,
66
+ sslCertFilePassword,
67
+ sslKeyFile,
68
+ sslRejectUnauthorized,
69
+ trustServerCertificate,
70
+ };
71
+ return {
72
+ ...res,
73
+ ssl: await extractConnectionSslParams(res),
74
+ };
39
75
  }
40
76
 
41
77
  let storageConnection = null;
@@ -47,7 +83,7 @@ async function getStorageConnectionCore() {
47
83
  return [storageConnection, storageDriver];
48
84
  }
49
85
 
50
- const dbConnectionParams = getDbConnectionParams();
86
+ const dbConnectionParams = await getDbConnectionParams();
51
87
 
52
88
  if (!dbConnectionParams) {
53
89
  return [null, null];
@@ -125,6 +161,10 @@ async function storageSelectFmt(sql, ...params) {
125
161
  return resp.rows;
126
162
  }
127
163
 
164
+ async function storageSqlCommandFmt(sql, ...params) {
165
+ await storageSelectFmt(sql, ...params);
166
+ }
167
+
128
168
  async function storageReadUserRolePermissions(userId) {
129
169
  const resp = await storageSelectFmt(
130
170
  `
@@ -213,4 +253,5 @@ module.exports = {
213
253
  storageReadConfig,
214
254
  storageWriteConfig,
215
255
  getStorageConnectionError,
256
+ storageSqlCommandFmt,
216
257
  };
@@ -1,5 +1,5 @@
1
1
 
2
2
  module.exports = {
3
- version: '6.1.6',
4
- buildTime: '2025-02-04T16:06:06.228Z'
3
+ version: '6.2.1',
4
+ buildTime: '2025-02-28T09:57:07.127Z'
5
5
  };
package/src/main.js CHANGED
@@ -78,6 +78,8 @@ function start() {
78
78
  app.use(getExpressPath('/'), express.static('/home/dbgate-docker/public'));
79
79
  } else if (platformInfo.isAwsUbuntuLayout) {
80
80
  app.use(getExpressPath('/'), express.static('/home/ubuntu/build/public'));
81
+ } else if (platformInfo.isAzureUbuntuLayout) {
82
+ app.use(getExpressPath('/'), express.static('/home/azureuser/build/public'));
81
83
  } else if (processArgs.runE2eTests) {
82
84
  app.use(getExpressPath('/'), express.static(path.resolve('packer/build/public')));
83
85
  } else if (platformInfo.isNpmDist) {
@@ -140,6 +142,10 @@ function start() {
140
142
  const port = process.env.PORT || 3000;
141
143
  logger.info(`DbGate API listening on port ${port} (AWS AMI build)`);
142
144
  server.listen(port);
145
+ } else if (platformInfo.isAzureUbuntuLayout) {
146
+ const port = process.env.PORT || 3000;
147
+ logger.info(`DbGate API listening on port ${port} (Azure VM build)`);
148
+ server.listen(port);
143
149
  } else if (platformInfo.isNpmDist) {
144
150
  getPort({
145
151
  port: parseInt(
@@ -1,6 +1,6 @@
1
1
  const childProcessChecker = require('../utility/childProcessChecker');
2
2
  const requireEngineDriver = require('../utility/requireEngineDriver');
3
- const connectUtility = require('../utility/connectUtility');
3
+ const { connectUtility } = require('../utility/connectUtility');
4
4
  const { handleProcessCommunication } = require('../utility/processComm');
5
5
  const { pickSafeConnectionInfo } = require('../utility/crypting');
6
6
  const _ = require('lodash');
@@ -11,7 +11,7 @@ const {
11
11
  extractErrorLogData,
12
12
  } = require('dbgate-tools');
13
13
  const requireEngineDriver = require('../utility/requireEngineDriver');
14
- const connectUtility = require('../utility/connectUtility');
14
+ const { connectUtility } = require('../utility/connectUtility');
15
15
  const { handleProcessCommunication } = require('../utility/processComm');
16
16
  const { SqlGenerator } = require('dbgate-tools');
17
17
  const generateDeploySql = require('../shell/generateDeploySql');
@@ -213,13 +213,12 @@ async function handleRunOperation({ msgid, operation, useTransaction }, skipRead
213
213
  }
214
214
  }
215
215
 
216
- async function handleQueryData({ msgid, sql }, skipReadonlyCheck = false) {
216
+ async function handleQueryData({ msgid, sql, range }, skipReadonlyCheck = false) {
217
217
  await waitConnected();
218
218
  const driver = requireEngineDriver(storedConnection);
219
219
  try {
220
220
  if (!skipReadonlyCheck) ensureExecuteCustomScript(driver);
221
- // console.log(sql);
222
- const res = await driver.query(dbhan, sql);
221
+ const res = await driver.query(dbhan, sql, { range });
223
222
  process.send({ msgtype: 'response', msgid, ...res });
224
223
  } catch (err) {
225
224
  process.send({
@@ -234,7 +233,7 @@ async function handleSqlSelect({ msgid, select }) {
234
233
  const driver = requireEngineDriver(storedConnection);
235
234
  const dmp = driver.createDumper();
236
235
  dumpSqlSelect(dmp, select);
237
- return handleQueryData({ msgid, sql: dmp.s }, true);
236
+ return handleQueryData({ msgid, sql: dmp.s, range: select.range }, true);
238
237
  }
239
238
 
240
239
  async function handleDriverDataCore(msgid, callMethod, { logName }) {
@@ -291,10 +290,14 @@ async function handleLoadKeyTableRange({ msgid, key, cursor, count }) {
291
290
  });
292
291
  }
293
292
 
294
- async function handleLoadFieldValues({ msgid, schemaName, pureName, field, search }) {
295
- return handleDriverDataCore(msgid, driver => driver.loadFieldValues(dbhan, { schemaName, pureName }, field, search), {
296
- logName: 'loadFieldValues',
297
- });
293
+ async function handleLoadFieldValues({ msgid, schemaName, pureName, field, search, dataType }) {
294
+ return handleDriverDataCore(
295
+ msgid,
296
+ driver => driver.loadFieldValues(dbhan, { schemaName, pureName }, field, search, dataType),
297
+ {
298
+ logName: 'loadFieldValues',
299
+ }
300
+ );
298
301
  }
299
302
 
300
303
  function ensureExecuteCustomScript(driver) {
@@ -336,6 +339,7 @@ async function handleSqlPreview({ msgid, objects, options }) {
336
339
  }, 500);
337
340
  }
338
341
  } catch (err) {
342
+ console.error(err);
339
343
  process.send({
340
344
  msgtype: 'response',
341
345
  msgid,
@@ -423,7 +427,11 @@ function start() {
423
427
  await handleMessage(message);
424
428
  } catch (err) {
425
429
  logger.error(extractErrorLogData(err), 'Error in DB connection');
426
- process.send({ msgtype: 'error', error: extractErrorMessage(err, 'Error processing message') });
430
+ process.send({
431
+ msgtype: 'error',
432
+ error: extractErrorMessage(err, 'Error processing message'),
433
+ msgid: message?.msgid,
434
+ });
427
435
  }
428
436
  });
429
437
  }
@@ -2,7 +2,7 @@ const stableStringify = require('json-stable-stringify');
2
2
  const { extractBoolSettingsValue, extractIntSettingsValue, getLogger, extractErrorLogData } = require('dbgate-tools');
3
3
  const childProcessChecker = require('../utility/childProcessChecker');
4
4
  const requireEngineDriver = require('../utility/requireEngineDriver');
5
- const connectUtility = require('../utility/connectUtility');
5
+ const { connectUtility } = require('../utility/connectUtility');
6
6
  const { handleProcessCommunication } = require('../utility/processComm');
7
7
  const logger = getLogger('srvconnProcess');
8
8
 
@@ -8,7 +8,7 @@ const { splitQuery } = require('dbgate-query-splitter');
8
8
  const { jsldir } = require('../utility/directories');
9
9
  const requireEngineDriver = require('../utility/requireEngineDriver');
10
10
  const { decryptConnection } = require('../utility/crypting');
11
- const connectUtility = require('../utility/connectUtility');
11
+ const { connectUtility } = require('../utility/connectUtility');
12
12
  const { handleProcessCommunication } = require('../utility/processComm');
13
13
  const { getLogger, extractIntSettingsValue, extractBoolSettingsValue } = require('dbgate-tools');
14
14
 
@@ -245,7 +245,47 @@ async function handleStopProfiler({ jslid }) {
245
245
  currentProfiler = null;
246
246
  }
247
247
 
248
- async function handleExecuteQuery({ sql }) {
248
+ async function handleExecuteControlCommand({ command }) {
249
+ lastActivity = new Date().getTime();
250
+
251
+ await waitConnected();
252
+ const driver = requireEngineDriver(storedConnection);
253
+
254
+ if (command == 'commitTransaction' && !allowExecuteCustomScript(driver)) {
255
+ process.send({
256
+ msgtype: 'info',
257
+ info: {
258
+ message: 'Connection without read-only sessions is read only',
259
+ severity: 'error',
260
+ },
261
+ });
262
+ process.send({ msgtype: 'done', skipFinishedMessage: true });
263
+ return;
264
+ //process.send({ msgtype: 'error', error: e.message });
265
+ }
266
+
267
+ executingScripts++;
268
+ try {
269
+ const dmp = driver.createDumper();
270
+ switch (command) {
271
+ case 'commitTransaction':
272
+ await dmp.commitTransaction();
273
+ break;
274
+ case 'rollbackTransaction':
275
+ await dmp.rollbackTransaction();
276
+ break;
277
+ case 'beginTransaction':
278
+ await dmp.beginTransaction();
279
+ break;
280
+ }
281
+ await driver.query(dbhan, dmp.s, { discardResult: true });
282
+ process.send({ msgtype: 'done', controlCommand: command });
283
+ } finally {
284
+ executingScripts--;
285
+ }
286
+ }
287
+
288
+ async function handleExecuteQuery({ sql, autoCommit }) {
249
289
  lastActivity = new Date().getTime();
250
290
 
251
291
  await waitConnected();
@@ -279,7 +319,7 @@ async function handleExecuteQuery({ sql }) {
279
319
  // handler.stream = stream;
280
320
  // resultIndex = handler.resultIndex;
281
321
  }
282
- process.send({ msgtype: 'done' });
322
+ process.send({ msgtype: 'done', autoCommit });
283
323
  } finally {
284
324
  executingScripts--;
285
325
  }
@@ -323,6 +363,7 @@ function handlePing() {
323
363
  const messageHandlers = {
324
364
  connect: handleConnect,
325
365
  executeQuery: handleExecuteQuery,
366
+ executeControlCommand: handleExecuteControlCommand,
326
367
  executeReader: handleExecuteReader,
327
368
  startProfiler: handleStartProfiler,
328
369
  stopProfiler: handleStopProfiler,
@@ -2,7 +2,7 @@ const stream = require('stream');
2
2
  const path = require('path');
3
3
  const { quoteFullName, fullNameToString, getLogger } = require('dbgate-tools');
4
4
  const requireEngineDriver = require('../utility/requireEngineDriver');
5
- const connectUtility = require('../utility/connectUtility');
5
+ const { connectUtility } = require('../utility/connectUtility');
6
6
  const logger = getLogger('dataDuplicator');
7
7
  const { DataDuplicator } = require('dbgate-datalib');
8
8
  const copyStream = require('./copyStream');
@@ -1,7 +1,7 @@
1
1
  const generateDeploySql = require('./generateDeploySql');
2
2
  const executeQuery = require('./executeQuery');
3
3
  const { ScriptDrivedDeployer } = require('dbgate-datalib');
4
- const connectUtility = require('../utility/connectUtility');
4
+ const { connectUtility } = require('../utility/connectUtility');
5
5
  const requireEngineDriver = require('../utility/requireEngineDriver');
6
6
  const loadModelFolder = require('../utility/loadModelFolder');
7
7
  const crypto = require('crypto');