diff --git a/packages/api/src/shell/executeQuery.js b/packages/api/src/shell/executeQuery.js
new file mode 100644
index 000000000..3ee97c19f
--- /dev/null
+++ b/packages/api/src/shell/executeQuery.js
@@ -0,0 +1,19 @@
+const goSplit = require('../utility/goSplit');
+const requireEngineDriver = require('../utility/requireEngineDriver');
+
+async function executeQuery({ connection, sql }) {
+ console.log(`Execute query ${sql}`);
+
+ const driver = requireEngineDriver(connection);
+ const pool = await driver.connect(connection);
+ console.log(`Connected.`);
+
+ for (const sqlItem of goSplit(sql)) {
+ console.log('Executing query', sqlItem);
+ await driver.query(pool, sqlItem);
+ }
+
+ console.log(`Query finished`);
+}
+
+module.exports = executeQuery;
diff --git a/packages/api/src/shell/index.js b/packages/api/src/shell/index.js
index 135af5ab8..77826c045 100644
--- a/packages/api/src/shell/index.js
+++ b/packages/api/src/shell/index.js
@@ -15,6 +15,8 @@ const finalizer = require('./finalizer');
const registerPlugins = require('./registerPlugins');
const requirePlugin = require('./requirePlugin');
const download = require('./download');
+const executeQuery = require('./executeQuery');
+const loadFile = require('./loadFile');
const dbgateApi = {
queryReader,
@@ -32,7 +34,8 @@ const dbgateApi = {
collectorWriter,
finalizer,
registerPlugins,
- download,
+ executeQuery,
+ loadFile,
};
requirePlugin.initialize(dbgateApi);
diff --git a/packages/api/src/shell/loadFile.js b/packages/api/src/shell/loadFile.js
new file mode 100644
index 000000000..8bc31977e
--- /dev/null
+++ b/packages/api/src/shell/loadFile.js
@@ -0,0 +1,10 @@
+const fs = require('fs-extra');
+const path = require('path');
+const { filesdir } = require('../utility/directories');
+
+async function loadFile(file) {
+ const text = await fs.readFile(path.join(filesdir(), file), { encoding: 'utf-8' });
+ return text;
+}
+
+module.exports = loadFile;
diff --git a/packages/tools/src/packageTools.ts b/packages/tools/src/packageTools.ts
index 6fd1d5639..54b5a5930 100644
--- a/packages/tools/src/packageTools.ts
+++ b/packages/tools/src/packageTools.ts
@@ -18,6 +18,15 @@ export function extractShellApiPlugins(functionName, props): string[] {
return res;
}
+export function extractPackageName(name): string {
+ if (!name) return null;
+ const nsMatch = name.match(/^([^@]+)@([^@]+)/);
+ if (nsMatch) {
+ return nsMatch[2];
+ }
+ return null;
+}
+
export function extractShellApiFunctionName(functionName) {
const nsMatch = functionName.match(/^([^@]+)@([^@]+)/);
if (nsMatch) {
diff --git a/packages/web/src/appobj/SavedFileAppObject.js b/packages/web/src/appobj/SavedFileAppObject.js
index 63da73193..39343027d 100644
--- a/packages/web/src/appobj/SavedFileAppObject.js
+++ b/packages/web/src/appobj/SavedFileAppObject.js
@@ -5,20 +5,23 @@ import { DropDownMenuItem } from '../modals/DropDownMenu';
import { AppObjectCore } from './AppObjectCore';
import useNewQuery from '../query/useNewQuery';
import { openNewTab } from '../utility/common';
-import { useSetOpenedTabs } from '../utility/globalState';
+import { useCurrentDatabase, useSetOpenedTabs } from '../utility/globalState';
+import ScriptWriter from '../impexp/ScriptWriter';
+import { extractPackageName } from 'dbgate-tools';
-function Menu({ data }) {
+function Menu({ data, menuExt = null }) {
const handleDelete = () => {
axios.post('files/delete', data);
};
return (
<>
Delete
+ {menuExt}
>
);
}
-export function SavedFileAppObjectBase({ data, commonProps, format, icon, onLoad }) {
+export function SavedFileAppObjectBase({ data, commonProps, format, icon, onLoad, menuExt = null }) {
const { file, folder } = data;
const onClick = async () => {
@@ -26,12 +29,48 @@ export function SavedFileAppObjectBase({ data, commonProps, format, icon, onLoad
onLoad(resp.data);
};
- return ;
+ return (
+ : Menu}
+ />
+ );
}
export function SavedSqlFileAppObject({ data, commonProps }) {
const { file, folder } = data;
const newQuery = useNewQuery();
+ const currentDatabase = useCurrentDatabase();
+ const setOpenedTabs = useSetOpenedTabs();
+
+ const connection = _.get(currentDatabase, 'connection');
+ const database = _.get(currentDatabase, 'name');
+
+ const handleGenerateExecute = () => {
+ const script = new ScriptWriter();
+ const conn = {
+ ..._.omit(connection, ['displayName', '_id']),
+ database,
+ };
+ script.put(`const sql = await dbgateApi.loadFile('${folder}/${file}');`)
+ script.put(`await dbgateApi.executeQuery({ sql, connection: ${JSON.stringify(conn)} });`)
+ // @ts-ignore
+ script.requirePackage(extractPackageName(conn.engine));
+
+ openNewTab(
+ setOpenedTabs,
+ {
+ title: 'Shell',
+ icon: 'img shell',
+ tabComponent: 'ShellTab',
+ },
+ script.getScript()
+ );
+ };
return (
Generate shell execute
+ ) : null
+ }
onLoad={(data) => {
newQuery({
title: file,
diff --git a/packages/web/src/impexp/ScriptWriter.js b/packages/web/src/impexp/ScriptWriter.js
index a20a48b85..68e987c87 100644
--- a/packages/web/src/impexp/ScriptWriter.js
+++ b/packages/web/src/impexp/ScriptWriter.js
@@ -2,7 +2,7 @@ import _ from 'lodash';
import { extractShellApiFunctionName, extractShellApiPlugins } from 'dbgate-tools';
export default class ScriptWriter {
- constructor(varCount) {
+ constructor(varCount = '0') {
this.s = '';
this.packageNames = [];
// this.engines = [];
@@ -24,6 +24,10 @@ export default class ScriptWriter {
this.packageNames.push(...extractShellApiPlugins(functionName, props));
}
+ requirePackage(packageName) {
+ this.packageNames.push(packageName);
+ }
+
copyStream(sourceVar, targetVar) {
this.put(`await dbgateApi.copyStream(${sourceVar}, ${targetVar});`);
}
@@ -32,7 +36,7 @@ export default class ScriptWriter {
this.put(`// ${s}`);
}
- getScript(extensions, schedule) {
+ getScript(schedule = null) {
const packageNames = this.packageNames;
let prefix = _.uniq(packageNames)
.map((packageName) => `// @require ${packageName}\n`)
diff --git a/packages/web/src/impexp/createImpExpScript.js b/packages/web/src/impexp/createImpExpScript.js
index 87c161665..7938ee216 100644
--- a/packages/web/src/impexp/createImpExpScript.js
+++ b/packages/web/src/impexp/createImpExpScript.js
@@ -182,7 +182,7 @@ export default async function createImpExpScript(extensions, values, addEditorIn
script.comment('@ImportExportConfigurator');
script.comment(JSON.stringify(values));
}
- return script.getScript(extensions, values.schedule);
+ return script.getScript(values.schedule);
}
export function getActionOptions(extensions, source, values, targetDbinfo) {