diff --git a/packages/api/src/controllers/serverConnections.js b/packages/api/src/controllers/serverConnections.js index 09466aa3d..28fd52cde 100644 --- a/packages/api/src/controllers/serverConnections.js +++ b/packages/api/src/controllers/serverConnections.js @@ -142,6 +142,7 @@ module.exports = { createDatabase_meta: true, async createDatabase({ conid, name }) { const opened = await this.ensureOpened(conid); + if (opened.connection.isReadOnly) return false; opened.subprocess.send({ msgtype: 'createDatabase', name }); return { status: 'ok' }; }, diff --git a/packages/tools/src/driverBase.ts b/packages/tools/src/driverBase.ts index 05058955a..a35cf2ab9 100644 --- a/packages/tools/src/driverBase.ts +++ b/packages/tools/src/driverBase.ts @@ -23,6 +23,7 @@ export const driverBase = { dumperClass: SqlDumper, dialect, databaseEngineTypes: ['sql'], + supportedCreateDatabase: true, async analyseFull(pool, version) { const analyser = new this.analyserClass(pool, this, version); diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 75ab67b9e..decc6533c 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -61,6 +61,7 @@ export interface EngineDriver { supportedKeyTypes: SupportedDbKeyType[]; supportsDatabaseUrl?: boolean; isElectronOnly?: boolean; + supportedCreateDatabase?: boolean; showConnectionField?: (field: string, values: any) => boolean; showConnectionTab?: (tab: 'ssl' | 'sshTunnel', values: any) => boolean; beforeConnectionSave?: (values: any) => any; diff --git a/packages/web/src/appobj/ConnectionAppObject.svelte b/packages/web/src/appobj/ConnectionAppObject.svelte index 7a2a70b32..1b9842169 100644 --- a/packages/web/src/appobj/ConnectionAppObject.svelte +++ b/packages/web/src/appobj/ConnectionAppObject.svelte @@ -59,6 +59,7 @@ }; const getContextMenu = () => { + const driver = $extensions.drivers.find(x => x.engine == data.engine); const config = getCurrentConfig(); const handleRefresh = () => { apiCall('server-connections/refresh', { conid: data._id }); @@ -146,10 +147,12 @@ text: 'Disconnect', onClick: handleDisconnect, }, - $openedConnections.includes(data._id) && { - text: 'Create database', - onClick: handleCreateDatabase, - }, + $openedConnections.includes(data._id) && + driver?.supportedCreateDatabase && + !data.isReadOnly && { + text: 'Create database', + onClick: handleCreateDatabase, + }, ], data.singleDatabase && [ { divider: true }, diff --git a/packages/web/src/appobj/DatabaseAppObject.svelte b/packages/web/src/appobj/DatabaseAppObject.svelte index cba517142..28431c2a4 100644 --- a/packages/web/src/appobj/DatabaseAppObject.svelte +++ b/packages/web/src/appobj/DatabaseAppObject.svelte @@ -158,6 +158,21 @@ openJsonDocument(db, name); }; + const handleGenerateScript = async () => { + const data = await apiCall('database-connections/export-keys', { + conid: connection?._id, + database: name, + options: { + keyPrefix: '', + }, + }); + + newQuery({ + title: 'Export #', + initialData: data, + }); + }; + async function handleConfirmSql(sql) { const resp = await apiCall('database-connections/run-script', { conid: connection._id, database: name, sql }); const { errorMessage } = resp || {}; @@ -172,18 +187,22 @@ const commands = _.flatten((apps || []).map(x => x.commands || [])); + const isSqlOrDoc = + driver?.databaseEngineTypes?.includes('sql') || driver?.databaseEngineTypes?.includes('document'); + return [ { onClick: handleNewQuery, text: 'New query', isNewQuery: true }, driver?.databaseEngineTypes?.includes('sql') && { onClick: handleNewTable, text: 'New table' }, driver?.databaseEngineTypes?.includes('document') && { onClick: handleNewCollection, text: 'New collection' }, { divider: true }, - !connection.isReadOnly && { onClick: handleImport, text: 'Import' }, - { onClick: handleExport, text: 'Export' }, - { onClick: handleShowDiagram, text: 'Show diagram' }, - { onClick: handleSqlGenerator, text: 'SQL Generator' }, - { onClick: handleOpenJsonModel, text: 'Open model as JSON' }, - { onClick: handleExportModel, text: 'Export DB model - experimental' }, - _.get($currentDatabase, 'connection._id') && + isSqlOrDoc && !connection.isReadOnly && { onClick: handleImport, text: 'Import' }, + isSqlOrDoc && { onClick: handleExport, text: 'Export' }, + isSqlOrDoc && { onClick: handleShowDiagram, text: 'Show diagram' }, + isSqlOrDoc && { onClick: handleSqlGenerator, text: 'SQL Generator' }, + isSqlOrDoc && { onClick: handleOpenJsonModel, text: 'Open model as JSON' }, + isSqlOrDoc && { onClick: handleExportModel, text: 'Export DB model - experimental' }, + isSqlOrDoc && + _.get($currentDatabase, 'connection._id') && (_.get($currentDatabase, 'connection._id') != _.get(connection, '_id') || (_.get($currentDatabase, 'connection._id') == _.get(connection, '_id') && _.get($currentDatabase, 'name') != _.get(connection, 'name'))) && { @@ -191,6 +210,8 @@ text: `Compare with ${_.get($currentDatabase, 'name')}`, }, + driver?.databaseEngineTypes?.includes('keyvalue') && { onClick: handleGenerateScript, text: 'Generate script' }, + _.get($currentDatabase, 'connection._id') == _.get(connection, '_id') && _.get($currentDatabase, 'name') == name && { onClick: handleDisconnect, text: 'Disconnect' }, @@ -240,6 +261,7 @@ import ErrorMessageModal from '../modals/ErrorMessageModal.svelte'; import ConfirmSqlModal from '../modals/ConfirmSqlModal.svelte'; import { filterAppsForDatabase } from '../utility/appTools'; + import newQuery from '../query/newQuery'; export let data; export let passProps; diff --git a/plugins/dbgate-plugin-redis/src/frontend/driver.js b/plugins/dbgate-plugin-redis/src/frontend/driver.js index b90199195..cf6a25990 100644 --- a/plugins/dbgate-plugin-redis/src/frontend/driver.js +++ b/plugins/dbgate-plugin-redis/src/frontend/driver.js @@ -24,6 +24,7 @@ const driver = { defaultPort: 6379, editorMode: 'text', databaseEngineTypes: ['keyvalue'], + supportedCreateDatabase: false, getQuerySplitterOptions: () => redisSplitterOptions, supportedKeyTypes: [ {