fix: flatten duckdb primary schemas in sidebar

This commit is contained in:
t8y2 2026-05-27 02:33:21 +08:00
parent 0c9ee34a82
commit e6e5309807
3 changed files with 83 additions and 3 deletions

View File

@ -36,3 +36,44 @@ export function buildDatabaseTreeNodes(
},
];
}
export function buildDuckDbConnectionTreeNodes(
connectionId: string,
databases: DatabaseInfo[],
primarySchemas: string[],
): TreeNode[] {
const schemaNodes = primarySchemas.flatMap((schema) => {
const name = schema.trim();
if (!name) return [];
return [
{
id: `${connectionId}:main:${name}`,
label: name,
type: "schema" as const,
connectionId,
database: "main",
schema: name,
isExpanded: false,
children: [],
},
];
});
const attachedCatalogNodes = databases.flatMap((db) => {
const name = db.name.trim();
if (!name || name === "main") return [];
return [
{
id: `${connectionId}:${name}`,
label: name,
type: "database" as const,
connectionId,
database: name,
isExpanded: false,
children: [],
},
];
});
return [...schemaNodes, ...attachedCatalogNodes];
}

View File

@ -21,7 +21,7 @@ import type { SqlCompletionColumn, SqlCompletionTable } from "@/lib/sqlCompletio
import * as api from "@/lib/api";
import { isTauriRuntime } from "@/lib/tauriRuntime";
import { isSchemaAware, usesTreeSchemaMode } from "@/lib/databaseCapabilities";
import { buildDatabaseTreeNodes } from "@/lib/databaseTree";
import { buildDatabaseTreeNodes, buildDuckDbConnectionTreeNodes } from "@/lib/databaseTree";
import { buildSqlServerDatabaseTreeNodes, SQLSERVER_DEFAULT_SCHEMA } from "@/lib/sqlServerTree";
import { findDatabaseTreeNode } from "@/lib/treeRefreshTarget";
import { shouldMarkDisconnected } from "@/lib/connectionHealth";
@ -689,7 +689,27 @@ export const useConnectionStore = defineStore("connection", () => {
if (useCachedChildren(node, options)) return;
const config = getConfig(connectionId);
if (config?.db_type === "dameng" || config?.db_type === "oracle") {
if (config?.db_type === "duckdb") {
const cacheKey = schemaCacheKey(connectionId, "duckdb-root");
if (!options?.force) {
const cached = await loadPersistedTreeChildren(node, cacheKey);
if (cached.hit) {
if (cached.isStale) refreshStaleTreeNode(node);
return;
}
}
const [databases, schemas] = await Promise.all([
api.listDatabases(connectionId),
api.listSchemas(connectionId, "main"),
]);
const children = withSavedSqlRoot(
connectionId,
buildDuckDbConnectionTreeNodes(connectionId, databases, schemas),
node,
);
setChildren(node, children);
await savePersistedTreeChildren(cacheKey, children);
} else if (config?.db_type === "dameng" || config?.db_type === "oracle") {
const effectiveDb = config.database || "";
const cacheKey = schemaCacheKey(connectionId, effectiveDb, "schemas");
if (!options?.force) {

View File

@ -1,6 +1,6 @@
import assert from "node:assert/strict";
import test from "node:test";
import { buildDatabaseTreeNodes } from "../../apps/desktop/src/lib/databaseTree.ts";
import { buildDatabaseTreeNodes, buildDuckDbConnectionTreeNodes } from "../../apps/desktop/src/lib/databaseTree.ts";
test("设置默认库后侧边栏数据库树仍保留全部数据库", () => {
const nodes = buildDatabaseTreeNodes("conn-1", [{ name: "campaign_data" }, { name: "cms" }, { name: "mk_campaign" }]);
@ -35,3 +35,22 @@ test("tree schema mode can show a default node when no catalog is returned", ()
assert.equal(nodes[0].database, "");
assert.equal(nodes[0].label, "tree.defaultDatabase");
});
test("DuckDB shows primary catalog schemas directly under the connection", () => {
const nodes = buildDuckDbConnectionTreeNodes(
"conn-1",
[{ name: "main" }, { name: "attached_reports" }],
["main", "mysql", "prod_sales"],
);
assert.deepEqual(
nodes.map((node) => [node.type, node.label, node.database, node.schema]),
[
["schema", "main", "main", "main"],
["schema", "mysql", "main", "mysql"],
["schema", "prod_sales", "main", "prod_sales"],
["database", "attached_reports", "attached_reports", undefined],
],
);
assert.equal(nodes.find((node) => node.label === "mysql")?.id, "conn-1:main:mysql");
});