diff --git a/packages/web/src/appobj/DatabaseAppObject.svelte b/packages/web/src/appobj/DatabaseAppObject.svelte
index 28431c2a4..a92010eda 100644
--- a/packages/web/src/appobj/DatabaseAppObject.svelte
+++ b/packages/web/src/appobj/DatabaseAppObject.svelte
@@ -167,6 +167,11 @@
},
});
+ if (data.errorMessage) {
+ showSnackbarError(data.errorMessage);
+ return;
+ }
+
newQuery({
title: 'Export #',
initialData: data,
@@ -252,7 +257,7 @@
import getElectron from '../utility/getElectron';
import openNewTab from '../utility/openNewTab';
import AppObjectCore from './AppObjectCore.svelte';
- import { showSnackbarSuccess } from '../utility/snackbar';
+ import { showSnackbarError, showSnackbarSuccess } from '../utility/snackbar';
import { findEngineDriver } from 'dbgate-tools';
import InputTextModal from '../modals/InputTextModal.svelte';
import { getDatabaseInfo, useUsedApps } from '../utility/metadataLoaders';
diff --git a/packages/web/src/modals/DbKeyAddItemModal.svelte b/packages/web/src/modals/DbKeyAddItemModal.svelte
index a6ed6de77..ffbf1931a 100644
--- a/packages/web/src/modals/DbKeyAddItemModal.svelte
+++ b/packages/web/src/modals/DbKeyAddItemModal.svelte
@@ -13,8 +13,9 @@
let item = {};
const handleSubmit = async () => {
- closeCurrentModal();
- onConfirm(item);
+ if (await onConfirm(item)) {
+ closeCurrentModal();
+ }
};
@@ -24,7 +25,7 @@
{
item = value;
diff --git a/packages/web/src/tabs/DbKeyDetailTab.svelte b/packages/web/src/tabs/DbKeyDetailTab.svelte
index 830ee92f4..35cbb1f24 100644
--- a/packages/web/src/tabs/DbKeyDetailTab.svelte
+++ b/packages/web/src/tabs/DbKeyDetailTab.svelte
@@ -24,6 +24,7 @@
import _ from 'lodash';
import DbKeyItemDetail from '../dbkeyvalue/DbKeyItemDetail.svelte';
import DbKeyAddItemModal from '../modals/DbKeyAddItemModal.svelte';
+ import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
export let conid;
export let database;
@@ -86,13 +87,18 @@
showModal(DbKeyAddItemModal, {
keyInfo,
onConfirm: async row => {
- await apiCall('database-connections/call-method', {
+ const res = await apiCall('database-connections/call-method', {
conid,
database,
method: keyInfo.keyType.addMethod,
args: [keyInfo.key, ...keyInfo.keyType.dbKeyFields.map(col => row[col.name])],
});
+ if (res.errorMessage) {
+ showModal(ErrorMessageModal, { message: res.errorMessage });
+ return false;
+ }
refresh();
+ return true;
},
});
}
diff --git a/packages/web/src/widgets/DbKeysTreeNode.svelte b/packages/web/src/widgets/DbKeysTreeNode.svelte
index d8cfcb9e6..600f24b90 100644
--- a/packages/web/src/widgets/DbKeysTreeNode.svelte
+++ b/packages/web/src/widgets/DbKeysTreeNode.svelte
@@ -5,12 +5,13 @@
import { plusExpandIcon } from '../icons/expandIcons';
import FontIcon from '../icons/FontIcon.svelte';
import ConfirmModal from '../modals/ConfirmModal.svelte';
-import InputTextModal from '../modals/InputTextModal.svelte';
+ import InputTextModal from '../modals/InputTextModal.svelte';
import { showModal } from '../modals/modalTools';
import newQuery from '../query/newQuery';
import { activeDbKeysStore } from '../stores';
import { apiCall } from '../utility/api';
import openNewTab from '../utility/openNewTab';
+import { showSnackbarError } from '../utility/snackbar';
import DbKeysSubTree from './DbKeysSubTree.svelte';
@@ -111,6 +112,11 @@ import InputTextModal from '../modals/InputTextModal.svelte';
},
});
+ if (data.errorMessage) {
+ showSnackbarError(data.errorMessage);
+ return;
+ }
+
newQuery({
title: 'Export #',
initialData: data,
diff --git a/plugins/dbgate-plugin-redis/src/backend/driver.js b/plugins/dbgate-plugin-redis/src/backend/driver.js
index 63eb1d421..a788cbf53 100644
--- a/plugins/dbgate-plugin-redis/src/backend/driver.js
+++ b/plugins/dbgate-plugin-redis/src/backend/driver.js
@@ -297,6 +297,14 @@ const driver = {
switch (method) {
case 'mdel':
return await this.deleteBranch(pool, args[0]);
+ case 'xaddjson':
+ let json;
+ try {
+ json = JSON.parse(args[2]);
+ } catch (e) {
+ throw new Error('Value must be valid JSON. ' + e.message);
+ }
+ return await pool.xadd(args[0], args[1] || '*', ..._.flatten(_.toPairs(json)));
}
return await pool[method](...args);
},
@@ -332,6 +340,22 @@ const driver = {
items: _.chunk(res[1], 2).map((item) => ({ key: item[0], value: item[1] })),
};
}
+ case 'stream': {
+ const res = await pool.xrange(key, cursor == 0 ? '-' : cursor, '+', 'COUNT', count);
+ let newCursor = 0;
+ if (res.length > 0) {
+ const id = res[res.length - 1][0];
+ const idParts = id.split('-');
+ newCursor = `${idParts[0]}-${parseInt(idParts[1] + 1)}`;
+ }
+ return {
+ cursor: newCursor,
+ items: res.map(([id, vals]) => ({
+ id,
+ value: JSON.stringify(_.fromPairs(_.chunk(vals, 2)), undefined, 2),
+ })),
+ };
+ }
}
return null;
},
diff --git a/plugins/dbgate-plugin-redis/src/frontend/driver.js b/plugins/dbgate-plugin-redis/src/frontend/driver.js
index cf6a25990..843b41d10 100644
--- a/plugins/dbgate-plugin-redis/src/frontend/driver.js
+++ b/plugins/dbgate-plugin-redis/src/frontend/driver.js
@@ -64,6 +64,14 @@ const driver = {
addMethod: 'hset',
showItemList: true,
},
+ {
+ name: 'stream',
+ label: 'Stream',
+ dbKeyFields: [{ name: 'id' }, { name: 'value' }],
+ keyColumn: 'id',
+ addMethod: 'xaddjson',
+ showItemList: true,
+ },
],
showConnectionField: (field, values) => {