From 5792ce1244f2f5c0bd6d06d997f40d711afc157c Mon Sep 17 00:00:00 2001 From: jearhe <0verme7753@gmail.com> Date: Fri, 21 Aug 2026 09:27:24 +0800 Subject: [PATCH] fix(doris): preserve single external catalog visibility --- .../database/dorisCatalogCapability.spec.ts | 19 ++++++++++++++++++- .../lib/database/databaseFeatureSupport.ts | 11 ++++++++++- apps/desktop/src/stores/connectionStore.ts | 4 ++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/lib/__tests__/database/dorisCatalogCapability.spec.ts b/apps/desktop/src/lib/__tests__/database/dorisCatalogCapability.spec.ts index 542083980c..81149c75cd 100644 --- a/apps/desktop/src/lib/__tests__/database/dorisCatalogCapability.spec.ts +++ b/apps/desktop/src/lib/__tests__/database/dorisCatalogCapability.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { connectionIsDorisFamilyCatalogCapable, isDorisFamilyCatalogCapable, isInternalDorisCatalog } from "@/lib/database/databaseFeatureSupport"; +import { connectionIsDorisFamilyCatalogCapable, isDorisFamilyCatalogCapable, isInternalDorisCatalog, shouldShowDorisCatalogTree } from "@/lib/database/databaseFeatureSupport"; import type { ConnectionConfig } from "@/types/database"; function conn(db_type: ConnectionConfig["db_type"], driver_profile?: string | null): Pick { @@ -43,6 +43,23 @@ describe("connectionIsDorisFamilyCatalogCapable", () => { }); }); +describe("shouldShowDorisCatalogTree", () => { + const catalog = (name: string, catalog_type: string): { name: string; catalog_type: string } => ({ name, catalog_type }); + + it("keeps a single external catalog scoped in the tree", () => { + expect(shouldShowDorisCatalogTree([catalog("hive_catalog", "hive")])).toBe(true); + }); + + it("flattens a single built-in catalog", () => { + expect(shouldShowDorisCatalogTree([catalog("internal", "internal")])).toBe(false); + expect(shouldShowDorisCatalogTree([catalog("default_catalog", "Internal")])).toBe(false); + }); + + it("keeps the catalog layer when internal and external catalogs are visible", () => { + expect(shouldShowDorisCatalogTree([catalog("internal", "internal"), catalog("iceberg", "iceberg")])).toBe(true); + }); +}); + describe("isInternalDorisCatalog", () => { it("detects Doris internal catalog by type", () => { expect(isInternalDorisCatalog("internal", "internal")).toBe(true); diff --git a/apps/desktop/src/lib/database/databaseFeatureSupport.ts b/apps/desktop/src/lib/database/databaseFeatureSupport.ts index 7fea054dca..0923d600c9 100644 --- a/apps/desktop/src/lib/database/databaseFeatureSupport.ts +++ b/apps/desktop/src/lib/database/databaseFeatureSupport.ts @@ -1,4 +1,4 @@ -import type { ConnectionConfig, DatabaseType, TreeNodeType } from "@/types/database"; +import type { CatalogInfo, ConnectionConfig, DatabaseType, TreeNodeType } from "@/types/database"; import { supportsDatabaseFeature } from "@/lib/database/databaseDriverManifest"; import { canEditTableStructure } from "@/lib/table/tableStructureCapabilities"; import { CLEARABLE_QUERY_SCHEMA_TYPES, DATABASE_OBJECT_TREE_TYPES, DATABASE_SCHEMA_QUALIFIED_TYPES, FETCH_FIRST_TYPES, PG_LIKE_STRUCTURE_TYPES, PG_VACUUM_TYPES, SCHEMA_AWARE_TYPES, SINGLE_DATABASE_TYPES, TREE_SCHEMA_TYPES } from "@/lib/database/databaseCapabilitySets"; @@ -45,6 +45,15 @@ export function isInternalDorisCatalog(catalogType?: string | null, catalogName? return (catalogName ?? "").trim() === "internal"; } +/** + * Keep the catalog grouping layer whenever SHOW CATALOGS exposes an external + * catalog. A single visible external catalog still carries namespace + * information that cannot be represented by the flat database tree. + */ +export function shouldShowDorisCatalogTree(catalogs: readonly CatalogInfo[]): boolean { + return catalogs.some((catalog) => !isInternalDorisCatalog(catalog.catalog_type, catalog.name)); +} + export function usesTreeSchemaMode(dbType?: DatabaseType): boolean { return !!dbType && TREE_SCHEMA_TYPES.has(dbType); } diff --git a/apps/desktop/src/stores/connectionStore.ts b/apps/desktop/src/stores/connectionStore.ts index d049734826..c00b25b77c 100644 --- a/apps/desktop/src/stores/connectionStore.ts +++ b/apps/desktop/src/stores/connectionStore.ts @@ -68,7 +68,7 @@ import { mergeSqlObjectNavigationType, sqlObjectNavigationTypeFromTableType } fr import * as api from "@/lib/backend/api"; import { isTauriRuntime } from "@/lib/backend/tauriRuntime"; import { useTunnelProfileStore } from "@/stores/tunnelProfileStore"; -import { connectionIsDorisFamilyCatalogCapable, isInternalDorisCatalog, isSchemaAware, normalizeSidebarObjectKind, schemaNodeHasLoadableName, sidebarObjectKindsForDatabase, supportsPackageMemberExpansion, usesTreeSchemaMode } from "@/lib/database/databaseCapabilities"; +import { connectionIsDorisFamilyCatalogCapable, isInternalDorisCatalog, isSchemaAware, normalizeSidebarObjectKind, schemaNodeHasLoadableName, shouldShowDorisCatalogTree, sidebarObjectKindsForDatabase, supportsPackageMemberExpansion, usesTreeSchemaMode } from "@/lib/database/databaseCapabilities"; import { connectionDatabaseMetadataSchema, connectionObjectTreeNodeSchema, @@ -3869,7 +3869,7 @@ export const useConnectionStore = defineStore("connection", () => { return null; }); } - if (dorisCatalogs && dorisCatalogs.length > 1) { + if (dorisCatalogs && shouldShowDorisCatalogTree(dorisCatalogs)) { const cacheKey = schemaCacheKey(connectionId, "doris-catalogs"); if (!options?.force) { const cached = await loadPersistedTreeChildren(node, cacheKey, load);