diff --git a/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue b/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue
index 8007e7f4e..39ccf1d6e 100644
--- a/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue
+++ b/apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue
@@ -4802,11 +4802,6 @@ function handleRowKeydown(node: TreeNode, event: KeyboardEvent) {
onKeydown(event);
}
-function openPrimaryVisibleFilter(node: TreeNode) {
- activateRuntimeNode(node);
- openVisibleDatabasesDialog();
-}
-
function openDataInNewTab(node: TreeNode) {
activateRuntimeNode(node);
openDataInNewTabImmediately(node);
@@ -4827,7 +4822,6 @@ defineExpose({
handleRowClick,
handleRowDoubleClick,
handleRowKeydown,
- openPrimaryVisibleFilter,
openDataInNewTab,
requestPaste,
toggleNode,
diff --git a/apps/desktop/src/components/sidebar/SidebarVisibleFilterControl.vue b/apps/desktop/src/components/sidebar/SidebarVisibleFilterControl.vue
deleted file mode 100644
index 1b5de5423..000000000
--- a/apps/desktop/src/components/sidebar/SidebarVisibleFilterControl.vue
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
diff --git a/apps/desktop/src/components/sidebar/TreeItem.vue b/apps/desktop/src/components/sidebar/TreeItem.vue
index a87c427dd..f06481af0 100644
--- a/apps/desktop/src/components/sidebar/TreeItem.vue
+++ b/apps/desktop/src/components/sidebar/TreeItem.vue
@@ -70,7 +70,6 @@ import { useDragSort } from "@/composables/useDragSort";
import { sidebarTreeRuntimeKey } from "@/lib/sidebar/sidebarTreeRuntime";
import { treeNodePinKey } from "@/lib/app/pinnedItems";
import { isTreeGroupNodeType } from "@/lib/sidebar/treeNodeGroup";
-import SidebarVisibleFilterControl from "./SidebarVisibleFilterControl.vue";
const { t } = useI18n();
@@ -1197,7 +1196,6 @@ function onKeydown(event: KeyboardEvent) {
>{{ trailingComment }}
-
{{ t("connection.readOnlyBadge") }}
diff --git a/apps/desktop/src/components/sidebar/VisibleDatabasesDialog.vue b/apps/desktop/src/components/sidebar/VisibleDatabasesDialog.vue
index 79f82aeb6..4f1cf403a 100644
--- a/apps/desktop/src/components/sidebar/VisibleDatabasesDialog.vue
+++ b/apps/desktop/src/components/sidebar/VisibleDatabasesDialog.vue
@@ -84,7 +84,6 @@ async function loadDatabases() {
searchText.value = "";
try {
const names = await loadObjectNames();
- connectionStore.recordPrimaryVisibleObjectNames(props.connectionId, names);
objectNames.value = names;
showSystemDatabases.value = false;
const configured = isSchemaFilterMode.value ? connection.value?.visible_schemas?.[databaseKey.value] : connection.value?.visible_databases;
diff --git a/apps/desktop/src/components/sidebar/__tests__/SidebarVisibleFilterControl.spec.ts b/apps/desktop/src/components/sidebar/__tests__/SidebarVisibleFilterControl.spec.ts
deleted file mode 100644
index 8a7a31adb..000000000
--- a/apps/desktop/src/components/sidebar/__tests__/SidebarVisibleFilterControl.spec.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-// @vitest-environment happy-dom
-
-import { createApp, defineComponent, h, nextTick, type App } from "vue";
-import { afterEach, describe, expect, it, vi } from "vitest";
-import i18n from "@/i18n";
-import SidebarVisibleFilterControl from "@/components/sidebar/SidebarVisibleFilterControl.vue";
-import { createSidebarTreeRuntime, sidebarTreeRuntimeKey, type SidebarTreeRuntimeHost } from "@/lib/sidebar/sidebarTreeRuntime";
-import type { SidebarVisibleFilterSummary } from "@/lib/sidebar/sidebarVisibleFilterSummary";
-import type { ConnectionConfig, TreeNode } from "@/types/database";
-
-const state: {
- config: Pick;
- summary: SidebarVisibleFilterSummary;
-} = {
- config: { db_type: "mysql", name: "MySQL" },
- summary: { mode: "database", isExplicit: true, selected: 1, total: 6 },
-};
-
-vi.mock("@/stores/connectionStore", () => ({
- useConnectionStore: () => ({
- getConfig: () => state.config,
- getSidebarVisibleFilterSummary: () => state.summary,
- }),
-}));
-
-const mountedApps: App[] = [];
-
-function runtimeHost(): SidebarTreeRuntimeHost {
- return {
- buildContextMenu: vi.fn(() => []),
- handleRowClick: vi.fn(),
- handleRowDoubleClick: vi.fn(),
- handleRowKeydown: vi.fn(),
- openPrimaryVisibleFilter: vi.fn(),
- openDataInNewTab: vi.fn(),
- requestPaste: vi.fn(() => false),
- toggleNode: vi.fn(),
- };
-}
-
-async function mountControl() {
- const node: TreeNode = { id: "connection-1", label: "MySQL", type: "connection", connectionId: "connection-1" };
- const container = document.createElement("div");
- document.body.append(container);
- const runtime = createSidebarTreeRuntime();
- const host = runtimeHost();
- runtime.bindHost(host);
- const app = createApp(
- defineComponent({
- setup: () => () => h(SidebarVisibleFilterControl, { node }),
- }),
- );
- mountedApps.push(app);
- app.use(i18n);
- app.provide(sidebarTreeRuntimeKey, runtime);
- app.mount(container);
- await nextTick();
- return { container, host, node };
-}
-
-afterEach(() => {
- for (const app of mountedApps.splice(0)) app.unmount();
- document.body.innerHTML = "";
- state.config = { db_type: "mysql", name: "MySQL" };
- state.summary = { mode: "database", isExplicit: true, selected: 1, total: 6 };
-});
-
-describe("SidebarVisibleFilterControl", () => {
- it("shows the selected/total count and opens the existing primary filter route", async () => {
- const { container, host, node } = await mountControl();
- const button = container.querySelector("[data-sidebar-visible-filter]");
-
- expect(button?.textContent).toBe("1/6");
- expect(button?.getAttribute("aria-label")).toContain("MySQL");
- button?.click();
- expect(host.openPrimaryVisibleFilter).toHaveBeenCalledWith(node);
- });
-
- it("keeps an accessible filter control before counts are available", async () => {
- state.summary = { mode: "database", isExplicit: false, selected: null, total: null };
- const { container } = await mountControl();
- const button = container.querySelector("[data-sidebar-visible-filter]");
-
- expect(button).not.toBeNull();
- expect(button?.textContent).toBe("");
- expect(button?.getAttribute("aria-label")).toContain("MySQL");
- });
-
- it("does not render for unsupported connection types", async () => {
- state.config = { db_type: "elasticsearch", name: "Search" };
- const { container } = await mountControl();
-
- expect(container.querySelector("[data-sidebar-visible-filter]")).toBeNull();
- });
-});
diff --git a/apps/desktop/src/components/sidebar/__tests__/TreeItem.loadMoreActivation.spec.ts b/apps/desktop/src/components/sidebar/__tests__/TreeItem.loadMoreActivation.spec.ts
index 9910e0137..a524f9f5d 100644
--- a/apps/desktop/src/components/sidebar/__tests__/TreeItem.loadMoreActivation.spec.ts
+++ b/apps/desktop/src/components/sidebar/__tests__/TreeItem.loadMoreActivation.spec.ts
@@ -61,7 +61,6 @@ function runtimeHost(): SidebarTreeRuntimeHost {
handleRowClick: vi.fn(),
handleRowDoubleClick: vi.fn(),
handleRowKeydown: vi.fn(),
- openPrimaryVisibleFilter: vi.fn(),
openDataInNewTab: vi.fn(),
requestPaste: vi.fn(() => false),
toggleNode: vi.fn(),
diff --git a/apps/desktop/src/composables/useSidebarConnectionMutationRuntime.ts b/apps/desktop/src/composables/useSidebarConnectionMutationRuntime.ts
index bac37b95b..f233c70a4 100644
--- a/apps/desktop/src/composables/useSidebarConnectionMutationRuntime.ts
+++ b/apps/desktop/src/composables/useSidebarConnectionMutationRuntime.ts
@@ -16,7 +16,6 @@ import { canConfigureVisibleSchemasForTreeNode } from "@/lib/database/databaseFe
import { canCloseSidebarDatabaseConnection } from "@/lib/sidebar/sidebarDatabaseOpenState";
import { selectedConnectionDeleteTargets, selectedConnectionDuplicateTargets } from "@/lib/sidebar/sidebarConnectionSelection";
import { connectionDeleteTargetSnapshot, showDeleteConfirm, showDeleteGroupConfirm, sidebarFormTarget } from "@/components/sidebar/sidebarTreeDialogState";
-import { connectionCanConfigureSidebarVisibleDatabases } from "@/lib/sidebar/sidebarVisibleFilterMenu";
interface SidebarConnectionMutationRuntimeOptions {
activeNode: ShallowRef;
@@ -235,7 +234,7 @@ export function useSidebarConnectionMutationRuntime(options: SidebarConnectionMu
const canConfigureVisibleDatabases = computed(() => {
if (activeNode.value.type !== "connection" || !activeNode.value.connectionId) return false;
const databaseType = connectionStore.getConfig(activeNode.value.connectionId)?.db_type;
- return connectionCanConfigureSidebarVisibleDatabases(databaseType);
+ return databaseType !== "elasticsearch" && databaseType !== "easysearch" && databaseType !== "qdrant" && databaseType !== "milvus" && databaseType !== "weaviate" && databaseType !== "chromadb" && databaseType !== "etcd" && databaseType !== "mq" && databaseType !== "nacos";
});
const canConfigureVisibleSchemas = computed(() => {
if (!activeNode.value.connectionId) return false;
diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts
index 3115eaf15..c5ebc6f7e 100644
--- a/apps/desktop/src/i18n/locales/en.ts
+++ b/apps/desktop/src/i18n/locales/en.ts
@@ -2435,7 +2435,6 @@ export default {
},
visibleDatabases: {
title: "Visible Databases",
- sidebarControlLabel: 'Configure visible databases for "{connection}"{count}',
description: 'Choose which databases are shown under "{connection}".',
searchPlaceholder: "Search databases...",
selectedCount: "{selected}/{total} selected",
@@ -2450,7 +2449,6 @@ export default {
},
visibleSchemas: {
title: "Schema Filter",
- sidebarControlLabel: 'Configure visible schemas for "{connection}"{count}',
description: 'Choose which schemas are shown under "{connection}".',
searchPlaceholder: "Search schemas...",
selectedCount: "{selected}/{total} selected",
diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts
index 6cb38c8cb..6564cd1ae 100644
--- a/apps/desktop/src/i18n/locales/es.ts
+++ b/apps/desktop/src/i18n/locales/es.ts
@@ -2377,7 +2377,6 @@ export default withEnglishFallback({
},
visibleDatabases: {
title: "Bases de datos visibles",
- sidebarControlLabel: 'Configurar bases de datos visibles para "{connection}"{count}',
description: 'Elige qué bases de datos se muestran bajo "{connection}".',
searchPlaceholder: "Buscar bases de datos...",
selectedCount: "{selected}/{total} seleccionadas",
@@ -2392,7 +2391,6 @@ export default withEnglishFallback({
},
visibleSchemas: {
title: "Filtro de Schema",
- sidebarControlLabel: 'Configurar schemas visibles para "{connection}"{count}',
description: 'Elige qué schemas se muestran bajo "{connection}".',
searchPlaceholder: "Buscar schemas...",
selectedCount: "{selected}/{total} seleccionados",
diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts
index 010429615..24b1c11dd 100644
--- a/apps/desktop/src/i18n/locales/it.ts
+++ b/apps/desktop/src/i18n/locales/it.ts
@@ -2375,7 +2375,6 @@ export default withEnglishFallback({
},
visibleDatabases: {
title: "Database Visibili",
- sidebarControlLabel: 'Configura i database visibili per "{connection}"{count}',
description: 'Scegli quali database mostrare sotto "{connection}".',
searchPlaceholder: "Cerca database...",
selectedCount: "{selected}/{total} selezionati",
@@ -2390,7 +2389,6 @@ export default withEnglishFallback({
},
visibleSchemas: {
title: "Filtro Schema",
- sidebarControlLabel: 'Configura gli schema visibili per "{connection}"{count}',
description: 'Scegli quali schema mostrare sotto "{connection}".',
searchPlaceholder: "Cerca schema...",
selectedCount: "{selected}/{total} selezionati",
diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts
index 0577dcad5..215036192 100644
--- a/apps/desktop/src/i18n/locales/ja.ts
+++ b/apps/desktop/src/i18n/locales/ja.ts
@@ -2402,7 +2402,6 @@ export default withEnglishFallback({
},
visibleDatabases: {
title: "表示するデータベース",
- sidebarControlLabel: "「{connection}」の表示データベースを設定{count}",
description: "「{connection}」の下に表示するデータベースを選択してください。",
searchPlaceholder: "データベースを検索...",
selectedCount: "{selected}/{total}件選択中",
@@ -2417,7 +2416,6 @@ export default withEnglishFallback({
},
visibleSchemas: {
title: "スキーマフィルター",
- sidebarControlLabel: "「{connection}」の表示スキーマを設定{count}",
description: "「{connection}」の下に表示するスキーマを選択してください。",
searchPlaceholder: "スキーマを検索...",
selectedCount: "{selected}/{total}件選択中",
diff --git a/apps/desktop/src/i18n/locales/ko.ts b/apps/desktop/src/i18n/locales/ko.ts
index bd8485b96..95f88f6e9 100644
--- a/apps/desktop/src/i18n/locales/ko.ts
+++ b/apps/desktop/src/i18n/locales/ko.ts
@@ -2317,7 +2317,6 @@ export default withEnglishFallback({
},
visibleDatabases: {
title: "표시할 데이터베이스",
- sidebarControlLabel: '"{connection}"의 표시할 데이터베이스 구성{count}',
description: '"{connection}" 아래에 표시할 데이터베이스를 선택하세요.',
searchPlaceholder: "데이터베이스 검색...",
selectedCount: "{selected}/{total} 선택됨",
@@ -2332,7 +2331,6 @@ export default withEnglishFallback({
},
visibleSchemas: {
title: "스키마 필터",
- sidebarControlLabel: '"{connection}"의 표시할 스키마 구성{count}',
description: '"{connection}" 아래에 표시할 스키마를 선택하세요.',
searchPlaceholder: "스키마 검색...",
selectedCount: "{selected}/{total} 선택됨",
diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts
index f382e769a..7e27efbc3 100644
--- a/apps/desktop/src/i18n/locales/pt-BR.ts
+++ b/apps/desktop/src/i18n/locales/pt-BR.ts
@@ -2377,7 +2377,6 @@ export default withEnglishFallback({
},
visibleDatabases: {
title: "Bancos de dados visíveis",
- sidebarControlLabel: 'Configurar bancos de dados visíveis para "{connection}"{count}',
description: 'Escolha quais bancos de dados são exibidos em "{connection}".',
searchPlaceholder: "Pesquisar bancos de dados...",
selectedCount: "{selected}/{total} selecionados",
@@ -2392,7 +2391,6 @@ export default withEnglishFallback({
},
visibleSchemas: {
title: "Filtro de Schema",
- sidebarControlLabel: 'Configurar schemas visíveis para "{connection}"{count}',
description: 'Escolha quais schemas são exibidos em "{connection}".',
searchPlaceholder: "Pesquisar schemas...",
selectedCount: "{selected}/{total} selecionados",
diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts
index 6b7ceddad..4d5435668 100644
--- a/apps/desktop/src/i18n/locales/zh-CN.ts
+++ b/apps/desktop/src/i18n/locales/zh-CN.ts
@@ -2436,7 +2436,6 @@ export default withEnglishFallback({
},
visibleDatabases: {
title: "显示数据库",
- sidebarControlLabel: "配置「{connection}」的可见数据库{count}",
description: "选择「{connection}」下要在侧边栏显示的数据库。",
searchPlaceholder: "搜索数据库...",
selectedCount: "已选择 {selected}/{total}",
@@ -2451,7 +2450,6 @@ export default withEnglishFallback({
},
visibleSchemas: {
title: "Schema 过滤器",
- sidebarControlLabel: "配置「{connection}」的可见 Schema{count}",
description: "选择「{connection}」下要在侧边栏显示的 Schema。",
searchPlaceholder: "搜索 Schema...",
selectedCount: "已选择 {selected}/{total}",
diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts
index 5af3103ec..2dfce18ae 100644
--- a/apps/desktop/src/i18n/locales/zh-TW.ts
+++ b/apps/desktop/src/i18n/locales/zh-TW.ts
@@ -2376,7 +2376,6 @@ export default withEnglishFallback({
},
visibleDatabases: {
title: "顯示資料庫",
- sidebarControlLabel: "設定「{connection}」的可見資料庫{count}",
description: "選擇「{connection}」下要在側邊欄顯示的資料庫。",
searchPlaceholder: "搜尋資料庫……",
selectedCount: "已選擇 {selected}/{total}",
@@ -2391,7 +2390,6 @@ export default withEnglishFallback({
},
visibleSchemas: {
title: "Schema 過濾器",
- sidebarControlLabel: "設定「{connection}」的可見 Schema{count}",
description: "選擇「{connection}」下要在側邊欄顯示的 Schema。",
searchPlaceholder: "搜尋 Schema……",
selectedCount: "已選擇 {selected}/{total}",
diff --git a/apps/desktop/src/lib/__tests__/sidebar/sidebarTreeRuntime.spec.ts b/apps/desktop/src/lib/__tests__/sidebar/sidebarTreeRuntime.spec.ts
index 5c175abf1..573e4305b 100644
--- a/apps/desktop/src/lib/__tests__/sidebar/sidebarTreeRuntime.spec.ts
+++ b/apps/desktop/src/lib/__tests__/sidebar/sidebarTreeRuntime.spec.ts
@@ -12,7 +12,6 @@ function host(): SidebarTreeRuntimeHost {
handleRowClick: vi.fn(),
handleRowDoubleClick: vi.fn(),
handleRowKeydown: vi.fn(),
- openPrimaryVisibleFilter: vi.fn(),
openDataInNewTab: vi.fn(),
requestPaste: vi.fn(() => false),
toggleNode: vi.fn(),
@@ -47,17 +46,6 @@ describe("sidebar tree runtime", () => {
expect(runtimeHost.handleRowClick).toHaveBeenCalledTimes(100);
});
- it("forwards the direct primary visible-filter action to the bound host", () => {
- const runtime = createSidebarTreeRuntime();
- const runtimeHost = host();
- const connection = { id: "connection-1", label: "Connection", type: "connection", connectionId: "connection-1" } satisfies TreeNode;
- runtime.bindHost(runtimeHost);
-
- runtime.openPrimaryVisibleFilter(connection);
-
- expect(runtimeHost.openPrimaryVisibleFilter).toHaveBeenCalledWith(connection);
- });
-
it("rejects superseded and disposed generations without affecting another runtime", () => {
const runtime = createSidebarTreeRuntime();
const otherRuntime = createSidebarTreeRuntime();
diff --git a/apps/desktop/src/lib/connection/connectionVisibleDatabases.ts b/apps/desktop/src/lib/connection/connectionVisibleDatabases.ts
index a1dcabc89..f35185953 100644
--- a/apps/desktop/src/lib/connection/connectionVisibleDatabases.ts
+++ b/apps/desktop/src/lib/connection/connectionVisibleDatabases.ts
@@ -3,9 +3,9 @@ import { filterDatabaseNamesForVisiblePicker, normalizeVisibleDatabaseSelection
const DRAFT_VISIBLE_DATABASES_PREFIX = "__visible_draft_";
-// Turso and Cloudflare D1 target one fixed SQLite-compatible `main` namespace;
-// non-database services expose their own root objects rather than database namespaces.
-const UNSUPPORTED_VISIBLE_DATABASE_TYPES = new Set(["turso", "cloudflare-d1", "elasticsearch", "easysearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper", "mq", "nacos"]);
+// Turso and Cloudflare D1 connections target one fixed SQLite-compatible `main` namespace;
+// listing account-level databases requires separate platform credentials, not the database connection.
+const UNSUPPORTED_VISIBLE_DATABASE_TYPES = new Set(["turso", "cloudflare-d1", "elasticsearch", "easysearch", "qdrant", "milvus", "weaviate", "chromadb", "etcd", "zookeeper"]);
type VisibleDatabaseConnectionFields = Pick<
ConnectionConfig,
diff --git a/apps/desktop/src/lib/sidebar/sidebarTreeRuntime.ts b/apps/desktop/src/lib/sidebar/sidebarTreeRuntime.ts
index 70c0ae57a..833abe5c2 100644
--- a/apps/desktop/src/lib/sidebar/sidebarTreeRuntime.ts
+++ b/apps/desktop/src/lib/sidebar/sidebarTreeRuntime.ts
@@ -18,7 +18,6 @@ export interface SidebarTreeRuntimeHost {
handleRowClick(node: TreeNode, clickDetail: number): void;
handleRowDoubleClick(node: TreeNode, event: MouseEvent): void;
handleRowKeydown(node: TreeNode, event: KeyboardEvent): void;
- openPrimaryVisibleFilter(node: TreeNode): void;
openDataInNewTab(node: TreeNode): void;
requestPaste(node: TreeNode): boolean;
toggleNode(node: TreeNode): void;
@@ -39,7 +38,6 @@ export interface SidebarTreeRuntime {
handleRowClick(node: TreeNode, clickDetail: number): void;
handleRowDoubleClick(node: TreeNode, event: MouseEvent): void;
handleRowKeydown(node: TreeNode, event: KeyboardEvent): void;
- openPrimaryVisibleFilter(node: TreeNode): void;
openDataInNewTab(node: TreeNode): void;
requestPaste(node: TreeNode): boolean;
toggleNode(node: TreeNode): void;
@@ -99,9 +97,6 @@ export function createSidebarTreeRuntime(): SidebarTreeRuntime {
handleRowKeydown(node, event) {
currentHost()?.handleRowKeydown(node, event);
},
- openPrimaryVisibleFilter(node) {
- currentHost()?.openPrimaryVisibleFilter(node);
- },
openDataInNewTab(node) {
currentHost()?.openDataInNewTab(node);
},
diff --git a/apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts b/apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts
index 262481706..49eb26b11 100644
--- a/apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts
+++ b/apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts
@@ -1,21 +1,8 @@
-import type { DatabaseType } from "@/types/database";
-import { connectionCanChooseVisibleDatabases } from "@/lib/connection/connectionVisibleDatabases";
-
-const CATALOG_SCOPED_VISIBLE_DATABASE_TYPES = new Set(["doris", "starrocks"]);
-
export type SidebarVisibleFilterMenuEntry = {
label: "objects" | "schemas";
target: "visible-databases" | "visible-schemas";
};
-export function connectionCanConfigureSidebarVisibleDatabases(databaseType: DatabaseType | undefined): boolean {
- // Doris and StarRocks can expose the same database name in multiple catalogs,
- // while `visible_databases` is still a flat name list. Keep the sidebar entry
- // unavailable until the persisted selection can preserve catalog identity.
- if (databaseType && CATALOG_SCOPED_VISIBLE_DATABASE_TYPES.has(databaseType)) return false;
- return connectionCanChooseVisibleDatabases(databaseType ? { db_type: databaseType } : undefined);
-}
-
export function sidebarConnectionVisibleFilterMenu(options: { canConfigureVisibleDatabases: boolean; canConfigureVisibleSchemas: boolean; databaseFilterUsesSchemas: boolean }): SidebarVisibleFilterMenuEntry[] {
if (!options.canConfigureVisibleDatabases) {
return options.canConfigureVisibleSchemas ? [{ label: "schemas", target: "visible-schemas" }] : [];
diff --git a/apps/desktop/src/lib/sidebar/sidebarVisibleFilterSummary.ts b/apps/desktop/src/lib/sidebar/sidebarVisibleFilterSummary.ts
deleted file mode 100644
index 6da557a0f..000000000
--- a/apps/desktop/src/lib/sidebar/sidebarVisibleFilterSummary.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import type { ConnectionConfig } from "@/types/database";
-import { connectionUsesVisibleSchemaFilter, filterDatabaseNamesForVisiblePicker, filterSchemaNamesForVisiblePicker, normalizeVisibleDatabaseSelection } from "@/lib/database/visibleDatabases";
-
-type SidebarVisibleFilterConnection = Pick;
-
-export type SidebarVisibleFilterSummary = {
- mode: "database" | "schema";
- isExplicit: boolean;
- selected: number | null;
- total: number | null;
-};
-
-export function sidebarVisibleFilterSummary(connection: SidebarVisibleFilterConnection, objectNames?: readonly string[]): SidebarVisibleFilterSummary {
- const mode = connectionUsesVisibleSchemaFilter(connection) ? "schema" : "database";
- const configured = mode === "schema" ? connection.visible_schemas?.[connection.database || ""] : connection.visible_databases;
- if (!objectNames) return { mode, isExplicit: Array.isArray(configured), selected: null, total: null };
-
- const names = [...objectNames];
- const defaultNames = mode === "schema" ? filterSchemaNamesForVisiblePicker(names, connection) : filterDatabaseNamesForVisiblePicker(names, connection);
- if (!Array.isArray(configured)) {
- return { mode, isExplicit: false, selected: defaultNames.length, total: defaultNames.length };
- }
-
- const selectedNames = normalizeVisibleDatabaseSelection(configured, names);
- const defaultNameSet = new Set(defaultNames);
- const includesSystemObject = selectedNames.some((name) => !defaultNameSet.has(name));
- return {
- mode,
- isExplicit: true,
- selected: selectedNames.length,
- total: includesSystemObject ? names.length : defaultNames.length,
- };
-}
diff --git a/apps/desktop/src/stores/__tests__/connectionStore.duckdbVisibleDatabases.spec.ts b/apps/desktop/src/stores/__tests__/connectionStore.duckdbVisibleDatabases.spec.ts
deleted file mode 100644
index c84de298c..000000000
--- a/apps/desktop/src/stores/__tests__/connectionStore.duckdbVisibleDatabases.spec.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-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();
- 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 duckDbConnection(visibleDatabases?: string[]): ConnectionConfig {
- return {
- id: "duckdb-1",
- name: "DuckDB",
- db_type: "duckdb",
- host: "",
- port: 0,
- username: "",
- password: "",
- database: "main",
- visible_databases: visibleDatabases,
- } as ConnectionConfig;
-}
-
-function connectionNode(connection: ConnectionConfig): TreeNode {
- return {
- id: connection.id,
- label: connection.name,
- type: "connection",
- connectionId: connection.id,
- isExpanded: false,
- children: [],
- };
-}
-
-function rootEntries(node: TreeNode | undefined) {
- return (node?.children ?? []).map((child) => ({
- type: child.type,
- database: child.database,
- schema: child.schema,
- label: child.label,
- }));
-}
-
-async function setupStore(visibleDatabases?: string[]) {
- const listDatabases = vi.fn().mockResolvedValue([{ name: "main" }, { name: "analytics" }, { name: "warehouse" }]);
- const listSchemas = vi.fn().mockResolvedValue(["main", "reporting"]);
- const saveConnections = vi.fn().mockResolvedValue(undefined);
- vi.doMock("@/lib/backend/tauriRuntime", () => ({ isTauriRuntime: () => false }));
- vi.doMock("@/lib/backend/api", () => ({
- checkConnectionHealth: vi.fn().mockResolvedValue(undefined),
- deleteSchemaCachePrefix: vi.fn().mockResolvedValue(undefined),
- listDatabases,
- listSchemas,
- loadSchemaCache: vi.fn().mockResolvedValue(null),
- saveConnections,
- saveSchemaCache: vi.fn().mockResolvedValue(undefined),
- saveSidebarLayout: vi.fn().mockResolvedValue(undefined),
- }));
-
- const { useConnectionStore } = await import("@/stores/connectionStore");
- const store = useConnectionStore();
- const connection = duckDbConnection(visibleDatabases);
- store.connections = [connection];
- store.connectedIds.add(connection.id);
- store.sidebarLayout = { groups: [], order: [{ type: "connection", id: connection.id }] };
- store.treeNodes = [connectionNode(connection)];
- return { store, connection, saveConnections };
-}
-
-describe("connectionStore DuckDB visible databases", () => {
- beforeEach(() => {
- vi.resetModules();
- vi.unstubAllGlobals();
- installLocalStorage();
- setActivePinia(createPinia());
- });
-
- it("keeps main schemas and hides attached databases when only main is visible", async () => {
- const { store, connection } = await setupStore();
-
- await store.loadDatabases(connection.id, { force: true });
- await store.setVisibleDatabases(connection.id, ["main"]);
-
- expect(rootEntries(store.treeNodes[0])).toEqual([
- { type: "schema", database: "main", schema: "main", label: "main" },
- { type: "schema", database: "main", schema: "reporting", label: "reporting" },
- ]);
- expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isExplicit: true, selected: 1, total: 3 });
- });
-
- it("hides main schemas and unselected attached databases", async () => {
- const { store, connection } = await setupStore();
-
- await store.loadDatabases(connection.id, { force: true });
- await store.setVisibleDatabases(connection.id, ["warehouse"]);
-
- expect(rootEntries(store.treeNodes[0])).toEqual([{ type: "database", database: "warehouse", schema: undefined, label: "warehouse" }]);
- expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isExplicit: true, selected: 1, total: 3 });
- });
-
- it("restores main schemas and every attached database after clearing the filter", async () => {
- const { store, connection, saveConnections } = await setupStore();
- await store.loadDatabases(connection.id, { force: true });
- await store.setVisibleDatabases(connection.id, ["warehouse"]);
-
- await store.clearVisibleDatabases(connection.id);
-
- expect(rootEntries(store.treeNodes[0])).toEqual([
- { type: "schema", database: "main", schema: "main", label: "main" },
- { type: "schema", database: "main", schema: "reporting", label: "reporting" },
- { type: "database", database: "analytics", schema: undefined, label: "analytics" },
- { type: "database", database: "warehouse", schema: undefined, label: "warehouse" },
- ]);
- expect(store.getSidebarVisibleFilterSummary(connection.id)).toEqual({ mode: "database", isExplicit: false, selected: 3, total: 3 });
- expect(saveConnections).toHaveBeenLastCalledWith([expect.objectContaining({ id: connection.id, visible_databases: undefined })]);
- });
-});
diff --git a/apps/desktop/src/stores/connectionStore.ts b/apps/desktop/src/stores/connectionStore.ts
index ef29ef736..0fc5e6ba4 100644
--- a/apps/desktop/src/stores/connectionStore.ts
+++ b/apps/desktop/src/stores/connectionStore.ts
@@ -122,7 +122,6 @@ import i18n from "@/i18n";
import type { MqAdminConfig } from "@/types/mq";
import { RABBITMQ_MQ_TENANT, resolveMqSystemKindFromConnection } from "@/lib/mq/mqConsoleDefaults";
import { applySidebarDatabaseStorage, applySidebarTableStorage, sidebarDatabaseNames, supportsSidebarDatabaseStorage, supportsSidebarTableStorage, type SidebarTableStorageScope } from "@/lib/sidebar/sidebarDatabaseStorage";
-import { sidebarVisibleFilterSummary } from "@/lib/sidebar/sidebarVisibleFilterSummary";
const PINNED_TREE_NODES_STORAGE_KEY = "dbx-pinned-tree-nodes";
const ACTIVE_CONNECTION_STORAGE_KEY = "dbx-active-connection";
@@ -344,7 +343,6 @@ export const useConnectionStore = defineStore("connection", () => {
const completionColumnsCache = ref>({});
const completionForeignKeysCache = ref>({});
const completionDatabasesCache = ref>({});
- const primaryVisibleObjectNames = ref>({});
const sqlServerCompletionContextCache = ref>({});
const elasticsearchCompletionIndicesCache = ref>({});
const redisCompletionKeysCache = ref>({});
@@ -2377,7 +2375,6 @@ export const useConnectionStore = defineStore("connection", () => {
clearConnectionError(id);
connectionErrorRevisions.delete(id);
connectedIds.value.delete(id);
- clearPrimaryVisibleObjectNames(id);
clearConnectionIdentifierQuote(id);
clearConnectionHealthCheck(id);
sidebarLayout.value = removeConnectionFromSidebarLayout(sidebarLayout.value, id);
@@ -2413,7 +2410,6 @@ export const useConnectionStore = defineStore("connection", () => {
connections.value = nextConnections;
rebuildTreeNodes();
if (!runtimeConfigChanged) return;
- clearPrimaryVisibleObjectNames(config.id);
connectedIds.value.delete(config.id);
clearConnectionIdentifierQuote(config.id);
clearConnectionHealthCheck(config.id);
@@ -2559,25 +2555,6 @@ export const useConnectionStore = defineStore("connection", () => {
await reloadConnectionDatabaseChildren(connectionId);
}
- function recordPrimaryVisibleObjectNames(connectionId: string, objectNames: readonly string[]) {
- const names = [...objectNames];
- const existing = primaryVisibleObjectNames.value[connectionId];
- if (existing?.length === names.length && existing.every((name, index) => name === names[index])) return;
- primaryVisibleObjectNames.value = { ...primaryVisibleObjectNames.value, [connectionId]: names };
- }
-
- function clearPrimaryVisibleObjectNames(connectionId: string) {
- if (!(connectionId in primaryVisibleObjectNames.value)) return;
- const next = { ...primaryVisibleObjectNames.value };
- delete next[connectionId];
- primaryVisibleObjectNames.value = next;
- }
-
- function getSidebarVisibleFilterSummary(connectionId: string) {
- const config = getConfig(connectionId);
- return config ? sidebarVisibleFilterSummary(config, primaryVisibleObjectNames.value[connectionId]) : null;
- }
-
async function clearVisibleDatabases(connectionId: string) {
const config = getConfig(connectionId);
if (!config || !Array.isArray(config.visible_databases)) return;
@@ -3060,16 +3037,10 @@ export const useConnectionStore = defineStore("connection", () => {
}
}
const [databases, schemas] = await Promise.all([withMetadataLoadTimeout(connectionId, api.listDatabases(connectionId), "databases"), withMetadataLoadTimeout(connectionId, api.listSchemas(connectionId, "main"), "schemas")]);
- const databaseNames = databases.map((database) => database.name);
- const visibleNames = filterDatabaseNamesForConnection(databaseNames, config);
- const visibleNameSet = new Set(visibleNames);
- const visibleDatabases = databases.filter((database) => visibleNameSet.has(database.name));
- const visibleSchemas = visibleNameSet.has("main") ? schemas : [];
- const children = withSavedSqlRoot(connectionId, buildDuckDbConnectionTreeNodes(connectionId, visibleDatabases, visibleSchemas), node);
+ const children = withSavedSqlRoot(connectionId, buildDuckDbConnectionTreeNodes(connectionId, databases, schemas), node);
if (isSidebarSearchQueryChanged(options)) return;
const targetNode = treeNodeLoadTarget(load);
if (!targetNode) return;
- recordPrimaryVisibleObjectNames(connectionId, databaseNames);
setChildren(targetNode, children);
await savePersistedConnectionTreeChildren(cacheKey, targetNode.children || children);
} else if (config && connectionUsesVisibleSchemaFilter(config)) {
@@ -3084,7 +3055,7 @@ export const useConnectionStore = defineStore("connection", () => {
return;
}
}
- const schemas = await withMetadataLoadTimeout(connectionId, api.listSchemas(connectionId, effectiveDb), "schemas");
+ const schemas = await withMetadataLoadTimeout(connectionId, api.listSchemas(connectionId, effectiveDb, true), "schemas");
const visibleSchemas = filterSchemaNamesForConnection(schemas, schemaFilterConfig, effectiveDb || "", { showSystemSchemas });
const schemaNodes: TreeNode[] = sortSidebarNames(visibleSchemas).map((s) => ({
id: `${connectionId}:${s}:${s}`,
@@ -3099,7 +3070,6 @@ export const useConnectionStore = defineStore("connection", () => {
if (isSidebarSearchQueryChanged(options)) return;
const targetNode = treeNodeLoadTarget(load);
if (!targetNode) return;
- recordPrimaryVisibleObjectNames(connectionId, schemas);
setChildren(targetNode, withSavedSqlRoot(connectionId, schemaNodes, targetNode));
await savePersistedConnectionTreeChildren(cacheKey, targetNode.children || schemaNodes);
} else {
@@ -3183,10 +3153,6 @@ export const useConnectionStore = defineStore("connection", () => {
if (isSidebarSearchQueryChanged(options)) return;
const targetNode = treeNodeLoadTarget(load);
if (!targetNode) return;
- recordPrimaryVisibleObjectNames(
- connectionId,
- databases.map((database) => database.name),
- );
setChildren(targetNode, children);
await savePersistedConnectionTreeChildren(cacheKey, targetNode.children || children);
}
@@ -3242,10 +3208,6 @@ export const useConnectionStore = defineStore("connection", () => {
const visibleNameSet = new Set(visibleNames);
const targetNode = treeNodeLoadTarget(load);
if (!targetNode) return;
- recordPrimaryVisibleObjectNames(
- connectionId,
- dbs.map((db) => String(db.db)),
- );
setChildren(
targetNode,
withSavedSqlRoot(
@@ -3549,7 +3511,6 @@ export const useConnectionStore = defineStore("connection", () => {
const visibleDbs = filterDatabaseNamesForConnection(dbs, config);
const targetNode = treeNodeLoadTarget(load);
if (!targetNode) return;
- recordPrimaryVisibleObjectNames(connectionId, dbs);
setChildren(
targetNode,
withSavedSqlRoot(
@@ -6937,8 +6898,6 @@ export const useConnectionStore = defineStore("connection", () => {
ensureVisibleDatabase,
setVisibleSchemas,
clearVisibleSchemas,
- recordPrimaryVisibleObjectNames,
- getSidebarVisibleFilterSummary,
removeConnection,
removeConnections,
editingConnectionId,
diff --git a/packages/app-tests/connectionVisibleDatabases.test.ts b/packages/app-tests/connectionVisibleDatabases.test.ts
index 198b562f8..f9b92387d 100644
--- a/packages/app-tests/connectionVisibleDatabases.test.ts
+++ b/packages/app-tests/connectionVisibleDatabases.test.ts
@@ -90,11 +90,6 @@ test("Turso does not offer a visible database filter for its fixed main namespac
assert.equal(connectionCanChooseVisibleDatabases(config({ db_type: "turso" })), false);
});
-test("non-database connection types do not offer visible database selection", () => {
- assert.equal(connectionCanChooseVisibleDatabases(config({ db_type: "mq" })), false);
- assert.equal(connectionCanChooseVisibleDatabases(config({ db_type: "nacos" })), false);
-});
-
test("OceanBase Oracle uses schema filtering for visible object selection", () => {
assert.equal(connectionUsesVisibleSchemaFilter(config({ db_type: "oceanbase-oracle" })), true);
assert.equal(connectionUsesVisibleSchemaFilter(config({ db_type: "mysql", driver_profile: "oceanbase" })), false);
diff --git a/packages/app-tests/sidebarRuntimeDecomposition.test.ts b/packages/app-tests/sidebarRuntimeDecomposition.test.ts
index 0b7aabaa4..2f52693dd 100644
--- a/packages/app-tests/sidebarRuntimeDecomposition.test.ts
+++ b/packages/app-tests/sidebarRuntimeDecomposition.test.ts
@@ -3,7 +3,6 @@ import { readFileSync } from "node:fs";
import { test } from "vitest";
const treeItem = readFileSync("apps/desktop/src/components/sidebar/TreeItem.vue", "utf8");
-const visibleFilterControl = readFileSync("apps/desktop/src/components/sidebar/SidebarVisibleFilterControl.vue", "utf8");
const connectionTree = readFileSync("apps/desktop/src/components/sidebar/ConnectionTree.vue", "utf8");
const runtimeHost = readFileSync("apps/desktop/src/components/sidebar/SidebarTreeRuntimeHost.vue", "utf8");
const dataOpenRuntime = readFileSync("apps/desktop/src/composables/useSidebarDataOpenRuntime.ts", "utf8");
@@ -34,15 +33,6 @@ test("one tree-level runtime serves every row renderer", () => {
assert.match(dataOpenRuntime, /canApplyDataTabMetadata/);
});
-test("connection rows expose the primary visible-filter control through the shared runtime", () => {
- assert.match(treeItem, //);
- assert.match(visibleFilterControl, /data-sidebar-visible-filter/);
- assert.match(visibleFilterControl, /control\.selected/);
- assert.match(visibleFilterControl, /treeRuntime\.openPrimaryVisibleFilter\(props\.node\)/);
- assert.match(runtimeHost, /function openPrimaryVisibleFilter\(node: TreeNode\)/);
- assert.match(runtimeHost, /openVisibleDatabasesDialog\(\)/);
-});
-
test("the persistent runtime releases detached tree nodes", () => {
const actionTarget = readFileSync("apps/desktop/src/lib/sidebar/sidebarActionTarget.ts", "utf8");
const connectionMutationRuntime = readFileSync("apps/desktop/src/composables/useSidebarConnectionMutationRuntime.ts", "utf8");
diff --git a/packages/app-tests/sidebarVisibleFilterMenu.test.ts b/packages/app-tests/sidebarVisibleFilterMenu.test.ts
index 626959759..8427a74e4 100644
--- a/packages/app-tests/sidebarVisibleFilterMenu.test.ts
+++ b/packages/app-tests/sidebarVisibleFilterMenu.test.ts
@@ -1,20 +1,6 @@
import assert from "node:assert/strict";
import { test } from "vitest";
-import { connectionCanConfigureSidebarVisibleDatabases, sidebarConnectionVisibleFilterMenu } from "../../apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts";
-
-test("connection-level visible filter support preserves the existing sidebar capability boundary", () => {
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("mysql"), true);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("oracle"), true);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("redis"), true);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("sqlite"), true);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("doris"), false);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("starrocks"), false);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("turso"), false);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("zookeeper"), false);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("elasticsearch"), false);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases("mq"), false);
- assert.equal(connectionCanConfigureSidebarVisibleDatabases(undefined), false);
-});
+import { sidebarConnectionVisibleFilterMenu } from "../../apps/desktop/src/lib/sidebar/sidebarVisibleFilterMenu.ts";
test("Dameng and Oracle schema-mode filters keep the connection-level dialog with one schema label", () => {
assert.deepEqual(
diff --git a/packages/app-tests/sidebarVisibleFilterSummary.test.ts b/packages/app-tests/sidebarVisibleFilterSummary.test.ts
deleted file mode 100644
index 852952be4..000000000
--- a/packages/app-tests/sidebarVisibleFilterSummary.test.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import assert from "node:assert/strict";
-import { test } from "vitest";
-import type { ConnectionConfig } from "../../apps/desktop/src/types/database.ts";
-import { sidebarVisibleFilterSummary } from "../../apps/desktop/src/lib/sidebar/sidebarVisibleFilterSummary.ts";
-
-function connection(overrides: Partial = {}): ConnectionConfig {
- return {
- id: "connection-1",
- name: "Connection",
- db_type: "mysql",
- host: "localhost",
- port: 3306,
- username: "root",
- ...overrides,
- };
-}
-
-test("summary remains actionable before primary namespace metadata is loaded", () => {
- assert.deepEqual(sidebarVisibleFilterSummary(connection({ visible_databases: ["app"] })), {
- mode: "database",
- isExplicit: true,
- selected: null,
- total: null,
- });
-});
-
-test("unfiltered database summary uses the picker's default non-system scope", () => {
- assert.deepEqual(sidebarVisibleFilterSummary(connection(), ["app", "analytics", "mysql", "sys"]), {
- mode: "database",
- isExplicit: false,
- selected: 2,
- total: 2,
- });
-});
-
-test("explicit database summary ignores stale names and retains the default denominator", () => {
- assert.deepEqual(sidebarVisibleFilterSummary(connection({ visible_databases: ["app", "removed"] }), ["app", "analytics", "mysql"]), {
- mode: "database",
- isExplicit: true,
- selected: 1,
- total: 2,
- });
-});
-
-test("selecting a system database expands the denominator like the picker", () => {
- assert.deepEqual(sidebarVisibleFilterSummary(connection({ visible_databases: ["app", "mysql"] }), ["app", "analytics", "mysql", "sys"]), {
- mode: "database",
- isExplicit: true,
- selected: 2,
- total: 4,
- });
-});
-
-test("schema-mode summary reads the primary schema filter for the configured database", () => {
- assert.deepEqual(
- sidebarVisibleFilterSummary(
- connection({
- db_type: "oracle",
- database: "ORCL",
- username: "APP",
- visible_schemas: { ORCL: ["APP"] },
- }),
- ["APP", "REPORTING", "SYS"],
- ),
- {
- mode: "schema",
- isExplicit: true,
- selected: 1,
- total: 2,
- },
- );
-});
-
-test("schema-mode summary includes system schemas when they are explicitly selected", () => {
- assert.deepEqual(
- sidebarVisibleFilterSummary(
- connection({
- db_type: "oracle",
- database: "ORCL",
- username: "APP",
- visible_schemas: { ORCL: ["APP", "SYS"] },
- }),
- ["APP", "REPORTING", "SYS"],
- ),
- {
- mode: "schema",
- isExplicit: true,
- selected: 2,
- total: 3,
- },
- );
-});