feat(redis): support database aliases
This commit is contained in:
parent
5309170bf7
commit
4a6422365b
|
|
@ -3254,6 +3254,7 @@ function connectionConfigForSubmit(id: string, generatedName = ""): ConnectionCo
|
|||
config.redis_cluster_nodes = undefined;
|
||||
config.redis_key_separator = undefined;
|
||||
config.redis_scan_page_size = undefined;
|
||||
config.redis_database_aliases = undefined;
|
||||
} else if (config.redis_connection_mode === "sentinel") {
|
||||
config.redis_sentinel_master = config.redis_sentinel_master?.trim() || "";
|
||||
config.redis_sentinel_nodes = normalizeRedisSentinelNodes(config.redis_sentinel_nodes || "");
|
||||
|
|
|
|||
|
|
@ -94,6 +94,11 @@ const {
|
|||
renameMongoCollectionPreview,
|
||||
renameMongoCollectionLoading,
|
||||
confirmRenameMongoCollection,
|
||||
showRedisDatabaseAliasDialog,
|
||||
redisDatabaseAliasInput,
|
||||
redisDatabaseAliasSaving,
|
||||
confirmRedisDatabaseAlias,
|
||||
clearRedisDatabaseAlias,
|
||||
showCreateSchemaDialog,
|
||||
createSchemaName,
|
||||
confirmCreateSchema,
|
||||
|
|
@ -150,6 +155,7 @@ watch(
|
|||
showCreateNacosNamespaceDialog,
|
||||
showEditNacosNamespaceDialog,
|
||||
showRenameMongoCollectionDialog,
|
||||
showRedisDatabaseAliasDialog,
|
||||
showCreateSchemaDialog,
|
||||
showEditSchemaCommentDialog,
|
||||
],
|
||||
|
|
@ -249,6 +255,26 @@ watch(
|
|||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog v-model:open="showRedisDatabaseAliasDialog">
|
||||
<DialogContent class="sm:max-w-[420px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{{ t("redis.databaseAliasTitle", { db: node.database }) }}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div class="grid gap-2">
|
||||
<Input v-model="redisDatabaseAliasInput" :placeholder="t('redis.databaseAliasPlaceholder')" :disabled="redisDatabaseAliasSaving" @keydown.enter.prevent="confirmRedisDatabaseAlias" />
|
||||
<p class="text-xs text-muted-foreground">{{ t("redis.databaseAliasHint") }}</p>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" :disabled="redisDatabaseAliasSaving" @click="clearRedisDatabaseAlias">{{ t("redis.clearDatabaseAlias") }}</Button>
|
||||
<Button variant="outline" :disabled="redisDatabaseAliasSaving" @click="showRedisDatabaseAliasDialog = false">{{ t("dangerDialog.cancel") }}</Button>
|
||||
<Button :disabled="redisDatabaseAliasSaving || !redisDatabaseAliasInput.trim()" @click="confirmRedisDatabaseAlias">
|
||||
<Loader2 v-if="redisDatabaseAliasSaving" class="mr-2 h-4 w-4 animate-spin" />
|
||||
{{ t("common.save") }}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog v-model:open="showStructurePreviewDialog">
|
||||
<DialogContent class="sm:max-w-[760px]">
|
||||
<DialogHeader>
|
||||
|
|
|
|||
|
|
@ -397,6 +397,12 @@ const {
|
|||
dropMongoIndex,
|
||||
dropAllMongoIndexes,
|
||||
flushRedisDb,
|
||||
prepareRedisDatabaseAliasDialog,
|
||||
confirmRedisDatabaseAlias,
|
||||
clearRedisDatabaseAlias,
|
||||
showRedisDatabaseAliasDialog,
|
||||
redisDatabaseAliasInput,
|
||||
redisDatabaseAliasSaving,
|
||||
confirmFlushRedisDb,
|
||||
confirmDropMongoDatabase,
|
||||
confirmDropMongoCollection,
|
||||
|
|
@ -575,7 +581,9 @@ async function toggle() {
|
|||
}
|
||||
} else if (node.type === "redis-db" && node.connectionId && node.database) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
const tabTitle = `${connectionStore.getConfig(node.connectionId)?.name || "Redis"}:db${node.database}`;
|
||||
const alias = connectionStore.getRedisDatabaseAlias(node.connectionId, node.database);
|
||||
const databaseLabel = alias ? `db${node.database} · ${alias}` : `db${node.database}`;
|
||||
const tabTitle = `${connectionStore.getConfig(node.connectionId)?.name || "Redis"}:${databaseLabel}`;
|
||||
queryStore.createTab(node.connectionId, node.database, tabTitle, "redis");
|
||||
} else if (node.type === "mq-tenant" && node.connectionId) {
|
||||
await connectionStore.ensureConnected(node.connectionId);
|
||||
|
|
@ -916,6 +924,12 @@ function openRenameMongoCollectionDialog() {
|
|||
prepareRenameMongoCollectionDialog();
|
||||
}
|
||||
|
||||
function openRedisDatabaseAliasDialog() {
|
||||
claimTreeItemDialogOwnership();
|
||||
routeTreeItemDialogController();
|
||||
prepareRedisDatabaseAliasDialog();
|
||||
}
|
||||
|
||||
function requestEditSelectedConnection(): boolean {
|
||||
const editTarget = selectedConnectionEditTarget(activeNode.value, selectedTreeNodesInVisibleOrder());
|
||||
if (!editTarget) return false;
|
||||
|
|
@ -3521,6 +3535,11 @@ function databaseSpecificDialogCapabilities() {
|
|||
renameMongoCollectionPreview,
|
||||
renameMongoCollectionLoading,
|
||||
confirmRenameMongoCollection,
|
||||
showRedisDatabaseAliasDialog,
|
||||
redisDatabaseAliasInput,
|
||||
redisDatabaseAliasSaving,
|
||||
confirmRedisDatabaseAlias,
|
||||
clearRedisDatabaseAlias,
|
||||
showCreateSchemaDialog,
|
||||
createSchemaName,
|
||||
confirmCreateSchema,
|
||||
|
|
@ -4017,6 +4036,7 @@ function buildSpecialSidebarMenu(context: SidebarMenuFactoryContext): boolean {
|
|||
}
|
||||
if (node.type === "redis-db") {
|
||||
items.push({ label: "", separator: true });
|
||||
items.push({ label: t("redis.setDatabaseAlias"), action: openRedisDatabaseAliasDialog, icon: Pencil });
|
||||
items.push({ label: t("redis.flushDb"), action: flushRedisDb, icon: Eraser, variant: "destructive" as const });
|
||||
}
|
||||
if (canDropMongoDatabase.value) {
|
||||
|
|
|
|||
|
|
@ -97,6 +97,9 @@ export const dropMongoIndexLoading = ref(false);
|
|||
export const showDropAllMongoIndexesConfirm = ref(false);
|
||||
export const dropAllMongoIndexesLoading = ref(false);
|
||||
export const showFlushRedisDbConfirm = ref(false);
|
||||
export const showRedisDatabaseAliasDialog = ref(false);
|
||||
export const redisDatabaseAliasInput = ref("");
|
||||
export const redisDatabaseAliasSaving = ref(false);
|
||||
export const showCreateSchemaDialog = ref(false);
|
||||
export const createSchemaName = ref("");
|
||||
export const showDropSchemaConfirm = ref(false);
|
||||
|
|
@ -139,6 +142,7 @@ const openFlags = [
|
|||
showDropMongoIndexConfirm,
|
||||
showDropAllMongoIndexesConfirm,
|
||||
showFlushRedisDbConfirm,
|
||||
showRedisDatabaseAliasDialog,
|
||||
showCreateSchemaDialog,
|
||||
showDropSchemaConfirm,
|
||||
showEditDatabasePropertiesDialog,
|
||||
|
|
@ -156,6 +160,8 @@ export function resetSidebarTreeDialogState() {
|
|||
createDatabasePreviewSql.value = "";
|
||||
createDatabaseAuthorizationResults.value = [];
|
||||
createDatabaseAuthorizationApplying.value = false;
|
||||
redisDatabaseAliasInput.value = "";
|
||||
redisDatabaseAliasSaving.value = false;
|
||||
sidebarTreeDialogOwner.value = null;
|
||||
sidebarDangerTarget.value = null;
|
||||
sidebarFormTarget.value = null;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ import {
|
|||
showDropDatabaseConfirm,
|
||||
dropDatabaseLoading,
|
||||
showFlushRedisDbConfirm,
|
||||
showRedisDatabaseAliasDialog,
|
||||
redisDatabaseAliasInput,
|
||||
redisDatabaseAliasSaving,
|
||||
showRenameMongoCollectionDialog,
|
||||
renameMongoCollectionName,
|
||||
renameMongoCollectionError,
|
||||
|
|
@ -231,6 +234,38 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
|||
showFlushRedisDbConfirm.value = true;
|
||||
}
|
||||
|
||||
function prepareRedisDatabaseAliasDialog() {
|
||||
const node = activeNode.value;
|
||||
redisDatabaseAliasInput.value = node.connectionId && node.database != null ? connectionStore.getRedisDatabaseAlias(node.connectionId, node.database) || "" : "";
|
||||
redisDatabaseAliasSaving.value = false;
|
||||
showRedisDatabaseAliasDialog.value = true;
|
||||
}
|
||||
|
||||
async function saveRedisDatabaseAlias(alias?: string) {
|
||||
const node = sidebarFormTarget.value ?? activeNode.value;
|
||||
if (node.type !== "redis-db" || !node.connectionId || node.database == null || redisDatabaseAliasSaving.value) return;
|
||||
redisDatabaseAliasSaving.value = true;
|
||||
try {
|
||||
await connectionStore.setRedisDatabaseAlias(node.connectionId, node.database, alias);
|
||||
showRedisDatabaseAliasDialog.value = false;
|
||||
const normalizedAlias = alias?.trim();
|
||||
toast(normalizedAlias ? t("redis.databaseAliasSaved", { db: node.database, alias: normalizedAlias }) : t("redis.databaseAliasCleared", { db: node.database }), 3000);
|
||||
} catch (error: any) {
|
||||
toast(t("connection.saveFailed", { message: error?.message || String(error) }), 5000);
|
||||
} finally {
|
||||
redisDatabaseAliasSaving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmRedisDatabaseAlias() {
|
||||
await saveRedisDatabaseAlias(redisDatabaseAliasInput.value);
|
||||
}
|
||||
|
||||
async function clearRedisDatabaseAlias() {
|
||||
redisDatabaseAliasInput.value = "";
|
||||
await saveRedisDatabaseAlias();
|
||||
}
|
||||
|
||||
async function confirmFlushRedisDb() {
|
||||
const node = sidebarDangerTarget.value ?? activeNode.value;
|
||||
if (node.type !== "redis-db" || !node.connectionId || !node.database) return;
|
||||
|
|
@ -387,6 +422,12 @@ export function useSidebarDatabaseSpecificMutationRuntime(options: SidebarDataba
|
|||
dropMongoIndex,
|
||||
dropAllMongoIndexes,
|
||||
flushRedisDb,
|
||||
prepareRedisDatabaseAliasDialog,
|
||||
confirmRedisDatabaseAlias,
|
||||
clearRedisDatabaseAlias,
|
||||
showRedisDatabaseAliasDialog,
|
||||
redisDatabaseAliasInput,
|
||||
redisDatabaseAliasSaving,
|
||||
confirmFlushRedisDb,
|
||||
confirmDropMongoDatabase,
|
||||
confirmDropMongoCollection,
|
||||
|
|
|
|||
|
|
@ -2971,6 +2971,13 @@ export default {
|
|||
summarySize: "size",
|
||||
},
|
||||
redis: {
|
||||
setDatabaseAlias: "Set Database Alias",
|
||||
databaseAliasTitle: "Alias for db{db}",
|
||||
databaseAliasPlaceholder: "e.g. orders, cache, development",
|
||||
databaseAliasHint: "The alias is for display and search only. Redis commands continue to use the numeric database index.",
|
||||
clearDatabaseAlias: "Clear Alias",
|
||||
databaseAliasSaved: "Alias for db{db} set to {alias}",
|
||||
databaseAliasCleared: "Alias for db{db} cleared",
|
||||
selectKey: "Select a key to view its value",
|
||||
noKeys: "No keys found",
|
||||
noKeysInScanHint: "No keys found in current scan range",
|
||||
|
|
|
|||
|
|
@ -2823,6 +2823,13 @@ export default withEnglishFallback({
|
|||
summarySize: "tamaño",
|
||||
},
|
||||
redis: {
|
||||
setDatabaseAlias: "Establecer alias de base de datos",
|
||||
databaseAliasTitle: "Alias para db{db}",
|
||||
databaseAliasPlaceholder: "p. ej. pedidos, caché, desarrollo",
|
||||
databaseAliasHint: "El alias solo se usa para mostrar y buscar. Los comandos de Redis siguen usando el índice numérico.",
|
||||
clearDatabaseAlias: "Borrar alias",
|
||||
databaseAliasSaved: "Alias de db{db} establecido en {alias}",
|
||||
databaseAliasCleared: "Alias de db{db} eliminado",
|
||||
createKeyTypeHelp: {
|
||||
string: "Valor único de hasta 512 MB; útil para caché y contadores.",
|
||||
hash: "Mapa plano campo-valor; leer un Hash grande completo es O(N).",
|
||||
|
|
|
|||
|
|
@ -2821,6 +2821,13 @@ export default withEnglishFallback({
|
|||
summarySize: "dimensione",
|
||||
},
|
||||
redis: {
|
||||
setDatabaseAlias: "Imposta alias database",
|
||||
databaseAliasTitle: "Alias per db{db}",
|
||||
databaseAliasPlaceholder: "es. ordini, cache, sviluppo",
|
||||
databaseAliasHint: "L'alias viene usato solo per visualizzazione e ricerca. I comandi Redis continuano a usare l'indice numerico.",
|
||||
clearDatabaseAlias: "Rimuovi alias",
|
||||
databaseAliasSaved: "Alias di db{db} impostato su {alias}",
|
||||
databaseAliasCleared: "Alias di db{db} rimosso",
|
||||
createKeyTypeHelp: {
|
||||
string: "Valore singolo fino a 512 MB; utile per cache e contatori.",
|
||||
hash: "Mappa campo-valore piatta; leggere un Hash grande intero è O(N).",
|
||||
|
|
|
|||
|
|
@ -2822,6 +2822,13 @@ export default withEnglishFallback({
|
|||
},
|
||||
},
|
||||
redis: {
|
||||
setDatabaseAlias: "データベースの別名を設定",
|
||||
databaseAliasTitle: "db{db} の別名",
|
||||
databaseAliasPlaceholder: "例:注文、キャッシュ、開発",
|
||||
databaseAliasHint: "別名は表示と検索にのみ使用されます。Redis コマンドは引き続き数値のデータベース番号を使用します。",
|
||||
clearDatabaseAlias: "別名をクリア",
|
||||
databaseAliasSaved: "db{db} の別名を {alias} に設定しました",
|
||||
databaseAliasCleared: "db{db} の別名をクリアしました",
|
||||
createKeyTypeHelp: {
|
||||
string: "最大 512 MB の単一値。キャッシュやカウンター向けです。",
|
||||
hash: "フラットなフィールド値マップ。大きな Hash 全読込は O(N) です。",
|
||||
|
|
|
|||
|
|
@ -2823,6 +2823,13 @@ export default withEnglishFallback({
|
|||
summarySize: "tamanho",
|
||||
},
|
||||
redis: {
|
||||
setDatabaseAlias: "Definir alias do banco",
|
||||
databaseAliasTitle: "Alias para db{db}",
|
||||
databaseAliasPlaceholder: "ex.: pedidos, cache, desenvolvimento",
|
||||
databaseAliasHint: "O alias é usado apenas para exibição e pesquisa. Os comandos Redis continuam usando o índice numérico.",
|
||||
clearDatabaseAlias: "Limpar alias",
|
||||
databaseAliasSaved: "Alias de db{db} definido como {alias}",
|
||||
databaseAliasCleared: "Alias de db{db} removido",
|
||||
createKeyTypeHelp: {
|
||||
string: "Valor único de até 512 MB; útil para cache e contadores.",
|
||||
hash: "Mapa plano campo-valor; ler um Hash grande inteiro é O(N).",
|
||||
|
|
|
|||
|
|
@ -2971,6 +2971,13 @@ export default withEnglishFallback({
|
|||
summarySize: "大小",
|
||||
},
|
||||
redis: {
|
||||
setDatabaseAlias: "设置数据库别名",
|
||||
databaseAliasTitle: "设置 db{db} 的别名",
|
||||
databaseAliasPlaceholder: "例如:订单、缓存、开发环境",
|
||||
databaseAliasHint: "别名仅用于显示和搜索,Redis 命令仍使用数字数据库编号。",
|
||||
clearDatabaseAlias: "清除别名",
|
||||
databaseAliasSaved: "已将 db{db} 的别名设置为「{alias}」",
|
||||
databaseAliasCleared: "已清除 db{db} 的别名",
|
||||
selectKey: "选择一个 key 查看值",
|
||||
noKeys: "未找到 key",
|
||||
noKeysInScanHint: "当前扫描范围内未命中匹配的 key",
|
||||
|
|
|
|||
|
|
@ -2494,6 +2494,13 @@ export default withEnglishFallback({
|
|||
noJoinSql: "沒有可複製的關係 SQL",
|
||||
},
|
||||
redis: {
|
||||
setDatabaseAlias: "設定資料庫別名",
|
||||
databaseAliasTitle: "設定 db{db} 的別名",
|
||||
databaseAliasPlaceholder: "例如:訂單、快取、開發環境",
|
||||
databaseAliasHint: "別名僅用於顯示和搜尋,Redis 命令仍使用數字資料庫編號。",
|
||||
clearDatabaseAlias: "清除別名",
|
||||
databaseAliasSaved: "已將 db{db} 的別名設定為「{alias}」",
|
||||
databaseAliasCleared: "已清除 db{db} 的別名",
|
||||
createKeyTypeHelp: {
|
||||
string: "最大 512 MB 的單一值;適合快取與計數器。",
|
||||
hash: "扁平欄位值映射;完整讀取大型 Hash 為 O(N)。",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { normalizeRedisDatabaseAliases, redisDatabaseAlias, redisDatabaseLabel } from "@/lib/redis/redisDatabaseAlias";
|
||||
|
||||
describe("redisDatabaseAlias", () => {
|
||||
it("normalizes numeric database keys and trims aliases", () => {
|
||||
expect(
|
||||
normalizeRedisDatabaseAliases({
|
||||
"0": " default ",
|
||||
"03": " orders ",
|
||||
invalid: "ignored",
|
||||
"4": "",
|
||||
}),
|
||||
).toEqual({
|
||||
"0": "default",
|
||||
"3": "orders",
|
||||
});
|
||||
});
|
||||
|
||||
it("returns undefined for empty alias maps", () => {
|
||||
expect(normalizeRedisDatabaseAliases({ "0": " " })).toBeUndefined();
|
||||
expect(normalizeRedisDatabaseAliases(null)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("looks up aliases without changing the Redis database index", () => {
|
||||
const aliases = { "3": "orders" };
|
||||
expect(redisDatabaseAlias(aliases, "03")).toBe("orders");
|
||||
expect(redisDatabaseAlias(aliases, "invalid")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("formats labels with aliases and key counts", () => {
|
||||
expect(redisDatabaseLabel(3, { "3": "orders" }, 128)).toBe("db3 · orders (128)");
|
||||
expect(redisDatabaseLabel(0, undefined, 0)).toBe("db0 (0)");
|
||||
expect(redisDatabaseLabel(2, { "2": "cache" })).toBe("db2 · cache");
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
export type RedisDatabaseAliases = Record<string, string>;
|
||||
|
||||
function redisDatabaseKey(database: string | number): string | null {
|
||||
const index = typeof database === "number" ? database : Number(database);
|
||||
return Number.isInteger(index) && index >= 0 ? String(index) : null;
|
||||
}
|
||||
|
||||
export function normalizeRedisDatabaseAliases(value: unknown): RedisDatabaseAliases | undefined {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
||||
|
||||
const aliases: RedisDatabaseAliases = {};
|
||||
for (const [database, alias] of Object.entries(value)) {
|
||||
const key = redisDatabaseKey(database);
|
||||
const normalizedAlias = typeof alias === "string" ? alias.trim() : "";
|
||||
if (key != null && normalizedAlias) aliases[key] = normalizedAlias;
|
||||
}
|
||||
return Object.keys(aliases).length > 0 ? aliases : undefined;
|
||||
}
|
||||
|
||||
export function redisDatabaseAlias(aliases: RedisDatabaseAliases | undefined, database: string | number): string | undefined {
|
||||
const key = redisDatabaseKey(database);
|
||||
return key == null ? undefined : aliases?.[key]?.trim() || undefined;
|
||||
}
|
||||
|
||||
export function redisDatabaseLabel(database: string | number, aliases?: RedisDatabaseAliases, totalKeyCount?: number): string {
|
||||
const key = redisDatabaseKey(database) ?? String(database);
|
||||
const alias = redisDatabaseAlias(aliases, key);
|
||||
const name = alias ? `db${key} · ${alias}` : `db${key}`;
|
||||
return totalKeyCount == null ? name : `${name} (${totalKeyCount})`;
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ConnectionConfig, TreeNode } from "@/types/database";
|
||||
|
||||
function installLocalStorage() {
|
||||
const data = new Map<string, string>();
|
||||
vi.stubGlobal("localStorage", {
|
||||
getItem: vi.fn((key: string) => data.get(key) ?? null),
|
||||
setItem: vi.fn((key: string, value: string) => data.set(key, value)),
|
||||
removeItem: vi.fn((key: string) => data.delete(key)),
|
||||
});
|
||||
}
|
||||
|
||||
function redisConnection(): ConnectionConfig {
|
||||
return {
|
||||
id: "redis-1",
|
||||
name: "Redis",
|
||||
db_type: "redis",
|
||||
host: "127.0.0.1",
|
||||
port: 6379,
|
||||
username: "",
|
||||
password: "",
|
||||
database: "0",
|
||||
};
|
||||
}
|
||||
|
||||
function seedRedisTree(store: { treeNodes: TreeNode[] }) {
|
||||
store.treeNodes.push({
|
||||
id: "redis-1",
|
||||
label: "Redis",
|
||||
type: "connection",
|
||||
connectionId: "redis-1",
|
||||
children: [
|
||||
{
|
||||
id: "redis-1:db3",
|
||||
label: "db3 (12)",
|
||||
type: "redis-db",
|
||||
connectionId: "redis-1",
|
||||
database: "3",
|
||||
loadedKeyCount: 0,
|
||||
totalKeyCount: 12,
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
describe("connectionStore Redis database aliases", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.unstubAllGlobals();
|
||||
installLocalStorage();
|
||||
setActivePinia(createPinia());
|
||||
});
|
||||
|
||||
it("persists an alias without disconnecting and keeps it during count refreshes", async () => {
|
||||
const saveConnections = vi.fn().mockResolvedValue(undefined);
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
saveConnections,
|
||||
saveSidebarLayout: vi.fn().mockResolvedValue(undefined),
|
||||
deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
|
||||
loadSchemaCache: vi.fn().mockResolvedValue(null),
|
||||
saveSchemaCache: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const store = useConnectionStore();
|
||||
store.addEphemeralConnection(redisConnection());
|
||||
seedRedisTree(store);
|
||||
|
||||
await store.setRedisDatabaseAlias("redis-1", "3", " orders ");
|
||||
|
||||
expect(store.getRedisDatabaseAlias("redis-1", 3)).toBe("orders");
|
||||
expect(store.connectedIds.has("redis-1")).toBe(true);
|
||||
expect(store.treeNodes[0].children?.[0].label).toBe("db3 · orders (12)");
|
||||
expect(saveConnections).toHaveBeenLastCalledWith([
|
||||
expect.objectContaining({
|
||||
id: "redis-1",
|
||||
redis_database_aliases: { "3": "orders" },
|
||||
}),
|
||||
]);
|
||||
|
||||
store.updateRedisDbKeyStats("redis-1", 3, { total: 15 });
|
||||
expect(store.treeNodes[0].children?.[0].label).toBe("db3 · orders (15)");
|
||||
});
|
||||
|
||||
it("clears an alias and removes the empty map from persisted config", async () => {
|
||||
const saveConnections = vi.fn().mockResolvedValue(undefined);
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
saveConnections,
|
||||
saveSidebarLayout: vi.fn().mockResolvedValue(undefined),
|
||||
deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
|
||||
loadSchemaCache: vi.fn().mockResolvedValue(null),
|
||||
saveSchemaCache: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const store = useConnectionStore();
|
||||
store.addEphemeralConnection({
|
||||
...redisConnection(),
|
||||
redis_database_aliases: { "3": "orders" },
|
||||
});
|
||||
seedRedisTree(store);
|
||||
|
||||
await store.setRedisDatabaseAlias("redis-1", 3);
|
||||
|
||||
expect(store.getRedisDatabaseAlias("redis-1", 3)).toBeUndefined();
|
||||
expect(store.treeNodes[0].children?.[0].label).toBe("db3 (12)");
|
||||
expect(saveConnections).toHaveBeenLastCalledWith([
|
||||
expect.objectContaining({
|
||||
id: "redis-1",
|
||||
redis_database_aliases: undefined,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps aliases for one-time Redis connections in memory without persisting secrets", async () => {
|
||||
const saveConnections = vi.fn().mockResolvedValue(undefined);
|
||||
vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
|
||||
vi.doMock("@/lib/backend/api", () => ({
|
||||
saveConnections,
|
||||
saveSidebarLayout: vi.fn().mockResolvedValue(undefined),
|
||||
deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
|
||||
loadSchemaCache: vi.fn().mockResolvedValue(null),
|
||||
saveSchemaCache: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const store = useConnectionStore();
|
||||
store.addEphemeralConnection({
|
||||
...redisConnection(),
|
||||
one_time: true,
|
||||
password: "one-time-secret",
|
||||
});
|
||||
seedRedisTree(store);
|
||||
|
||||
await store.setRedisDatabaseAlias("redis-1", 3, "orders");
|
||||
|
||||
expect(store.getRedisDatabaseAlias("redis-1", 3)).toBe("orders");
|
||||
expect(store.connections[0]).toEqual(expect.objectContaining({ password: "one-time-secret", redis_database_aliases: { "3": "orders" } }));
|
||||
expect(saveConnections).toHaveBeenLastCalledWith([]);
|
||||
});
|
||||
});
|
||||
|
|
@ -102,6 +102,7 @@ import { toMongoCollectionKind } from "@/lib/sidebar/mongoCollectionMutation";
|
|||
import { completionSchemasFromTree, completionTablesFromTree } from "@/lib/metadata/completionTreeIndex";
|
||||
import { kvRootNodeLabel } from "@/lib/kv/kvRootPresentation";
|
||||
import { REDIS_SCAN_PAGE_SIZE_DEFAULT } from "@/lib/redis/redisKeyPattern";
|
||||
import { normalizeRedisDatabaseAliases, redisDatabaseAlias, redisDatabaseLabel } from "@/lib/redis/redisDatabaseAlias";
|
||||
import { appendAgentDriverUpdateHint, hasAgentDriverUpdate, hasInstalledAgentVersion, type AgentDriverInstallState } from "@/lib/connection/agentDriverInstallHint";
|
||||
import { appendConnectionErrorHints } from "@/lib/connection/connectionErrorHints";
|
||||
import { appendVisibleDatabaseSelection } from "@/lib/connection/connectionVisibleDatabases";
|
||||
|
|
@ -286,11 +287,6 @@ type BeforeConnectHandler = (config: ConnectionConfig) => Promise<void>;
|
|||
|
||||
export const CONNECTION_ATTEMPT_CANCELLED_MESSAGE = "Connection attempt was cancelled";
|
||||
|
||||
function redisDbLabel(db: number, _loadedKeyCount?: number, totalKeyCount?: number): string {
|
||||
if (totalKeyCount == null) return `db${db}`;
|
||||
return `db${db} (${totalKeyCount})`;
|
||||
}
|
||||
|
||||
function metadataDriverProfile(config?: ConnectionConfig): string | undefined {
|
||||
return config?.driver_profile || config?.db_type;
|
||||
}
|
||||
|
|
@ -1033,6 +1029,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
query_timeout_secs: config.query_timeout_secs ?? 30,
|
||||
idle_timeout_secs: config.idle_timeout_secs ?? 60,
|
||||
keepalive_interval_secs: config.keepalive_interval_secs ?? DEFAULT_KEEPALIVE_INTERVAL_SECS,
|
||||
redis_database_aliases: normalizeRedisDatabaseAliases(config.redis_database_aliases),
|
||||
database_info: normalizeDatabaseConnectionInfo(config.database_info),
|
||||
};
|
||||
}
|
||||
|
|
@ -2389,6 +2386,37 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
return config?.database === database && database !== "";
|
||||
}
|
||||
|
||||
function getRedisDatabaseAlias(connectionId: string, database: string | number): string | undefined {
|
||||
return redisDatabaseAlias(getConfig(connectionId)?.redis_database_aliases, database);
|
||||
}
|
||||
|
||||
async function setRedisDatabaseAlias(connectionId: string, database: string | number, alias?: string) {
|
||||
const index = typeof database === "number" ? database : Number(database);
|
||||
const configIndex = connections.value.findIndex((connection) => connection.id === connectionId);
|
||||
const config = connections.value[configIndex];
|
||||
if (!config || config.db_type !== "redis" || !Number.isInteger(index) || index < 0) return;
|
||||
|
||||
const key = String(index);
|
||||
const aliases = { ...(config.redis_database_aliases || {}) };
|
||||
const normalizedAlias = alias?.trim() || "";
|
||||
if (normalizedAlias) aliases[key] = normalizedAlias;
|
||||
else delete aliases[key];
|
||||
|
||||
const redisDatabaseAliases = normalizeRedisDatabaseAliases(aliases);
|
||||
const nextConnections = [...connections.value];
|
||||
nextConnections[configIndex] = {
|
||||
...config,
|
||||
redis_database_aliases: redisDatabaseAliases,
|
||||
};
|
||||
await persistConnections(nextConnections);
|
||||
connections.value = nextConnections;
|
||||
|
||||
const node = findNode(treeNodes.value, `${connectionId}:db${key}`);
|
||||
if (node?.type === "redis-db") {
|
||||
node.label = redisDatabaseLabel(index, redisDatabaseAliases, node.totalKeyCount);
|
||||
}
|
||||
}
|
||||
|
||||
async function setVisibleDatabases(connectionId: string, databaseNames: string[]) {
|
||||
const config = getConfig(connectionId);
|
||||
if (!config) return;
|
||||
|
|
@ -3041,7 +3069,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
.filter((db) => visibleNameSet.has(String(db.db)))
|
||||
.map((db) => ({
|
||||
id: `${connectionId}:db${db.db}`,
|
||||
label: redisDbLabel(db.db, 0, db.keys),
|
||||
label: redisDatabaseLabel(db.db, config?.redis_database_aliases, db.keys),
|
||||
type: "redis-db" as const,
|
||||
connectionId,
|
||||
database: String(db.db),
|
||||
|
|
@ -3251,7 +3279,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
if (stats.totalDelta != null && node.totalKeyCount != null) {
|
||||
node.totalKeyCount = Math.max(0, node.totalKeyCount + stats.totalDelta);
|
||||
}
|
||||
node.label = redisDbLabel(db, node.loadedKeyCount, node.totalKeyCount);
|
||||
node.label = redisDatabaseLabel(db, getConfig(connectionId)?.redis_database_aliases, node.totalKeyCount);
|
||||
}
|
||||
|
||||
// Re-fetch the authoritative per-db key counts (INFO keyspace, lightweight) and update
|
||||
|
|
@ -5890,7 +5918,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
}
|
||||
|
||||
async function persistConnections(nextConnections: ConnectionConfig[] = connections.value) {
|
||||
await api.saveConnections(nextConnections);
|
||||
await api.saveConnections(nextConnections.filter((connection) => connection.one_time !== true));
|
||||
}
|
||||
|
||||
function persistSidebarLayoutDebounced() {
|
||||
|
|
@ -6462,6 +6490,8 @@ export const useConnectionStore = defineStore("connection", () => {
|
|||
setDefaultDatabase,
|
||||
clearDefaultDatabase,
|
||||
isDefaultDatabase,
|
||||
getRedisDatabaseAlias,
|
||||
setRedisDatabaseAlias,
|
||||
setVisibleDatabases,
|
||||
clearVisibleDatabases,
|
||||
ensureVisibleDatabase,
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ export interface ConnectionConfig {
|
|||
redis_cluster_nodes?: string;
|
||||
redis_key_separator?: string;
|
||||
redis_scan_page_size?: number;
|
||||
redis_database_aliases?: Record<string, string>;
|
||||
etcd_endpoints?: string;
|
||||
gbase_server?: string;
|
||||
informix_server?: string;
|
||||
|
|
|
|||
|
|
@ -645,6 +645,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -1159,6 +1159,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
@ -1215,6 +1216,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
@ -1335,6 +1337,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -3937,6 +3937,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -775,6 +775,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: crate::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -4668,6 +4668,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: crate::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -144,6 +144,8 @@ pub struct ConnectionConfig {
|
|||
pub redis_key_separator: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub redis_scan_page_size: Option<u64>,
|
||||
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
|
||||
pub redis_database_aliases: HashMap<String, String>,
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub etcd_endpoints: String,
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
|
|
@ -613,6 +615,8 @@ struct ConnectionConfigData {
|
|||
#[serde(default)]
|
||||
pub redis_scan_page_size: Option<u64>,
|
||||
#[serde(default)]
|
||||
pub redis_database_aliases: HashMap<String, String>,
|
||||
#[serde(default)]
|
||||
pub etcd_endpoints: String,
|
||||
#[serde(default)]
|
||||
pub gbase_server: String,
|
||||
|
|
@ -679,6 +683,7 @@ impl From<ConnectionConfigData> for ConnectionConfig {
|
|||
redis_cluster_nodes: data.redis_cluster_nodes,
|
||||
redis_key_separator: data.redis_key_separator,
|
||||
redis_scan_page_size: data.redis_scan_page_size,
|
||||
redis_database_aliases: data.redis_database_aliases,
|
||||
etcd_endpoints: data.etcd_endpoints,
|
||||
gbase_server: data.gbase_server,
|
||||
informix_server: data.informix_server,
|
||||
|
|
@ -2227,6 +2232,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
@ -2273,6 +2279,24 @@ mod tests {
|
|||
assert_eq!(serde_json::from_value::<ConnectionConfig>(value).unwrap().note, config.note);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redis_database_aliases_are_optional_and_round_trip() {
|
||||
let config = mysql_config("default", "secret", None);
|
||||
let value = serde_json::to_value(&config).unwrap();
|
||||
assert!(value.get("redis_database_aliases").is_none());
|
||||
assert!(serde_json::from_value::<ConnectionConfig>(value).unwrap().redis_database_aliases.is_empty());
|
||||
|
||||
let mut config = config;
|
||||
config.db_type = DatabaseType::Redis;
|
||||
config.redis_database_aliases.insert("3".to_string(), "orders".to_string());
|
||||
let value = serde_json::to_value(&config).unwrap();
|
||||
assert_eq!(value["redis_database_aliases"]["3"], "orders");
|
||||
assert_eq!(
|
||||
serde_json::from_value::<ConnectionConfig>(value).unwrap().redis_database_aliases,
|
||||
config.redis_database_aliases
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn database_identifier_whitespace_is_preserved_and_percent_encoded() {
|
||||
let mut config = mysql_config("root", "secret", Some(" analytics "));
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: String::new(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -895,6 +895,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: ":".to_string(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -324,6 +324,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: ":".to_string(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: ":".to_string(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
@ -327,6 +328,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: ":".to_string(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -680,6 +680,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: ":".to_string(),
|
||||
redis_scan_page_size: Some(1000),
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -4065,6 +4065,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
@ -5190,6 +5191,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -3063,6 +3063,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: crate::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -3978,6 +3978,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: ":".to_string(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
@ -4041,6 +4042,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: ":".to_string(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -4961,6 +4961,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ fn postgres_test_config(id: &str, port: u16) -> ConnectionConfig {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: dbx_core::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ fn live_postgres_config(
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: dbx_core::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ fn postgres_test_config(id: &str, database: &str) -> ConnectionConfig {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: dbx_core::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ fn live_sqlserver_config(id: &str, database: &str) -> dbx_core::models::connecti
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: dbx_core::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ fn live_sqlserver_config(id: &str, database: &str) -> dbx_core::models::connecti
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: dbx_core::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -453,6 +453,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: dbx_core::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ mod tests {
|
|||
redis_cluster_nodes: String::new(),
|
||||
redis_key_separator: dbx_core::models::connection::default_redis_key_separator(),
|
||||
redis_scan_page_size: None,
|
||||
redis_database_aliases: Default::default(),
|
||||
etcd_endpoints: String::new(),
|
||||
gbase_server: String::new(),
|
||||
informix_server: String::new(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue