From 3be08cb6cdd886b085cad371c77ceb40f3dbc44a Mon Sep 17 00:00:00 2001 From: tianqijiuyun-latiao <69459608+tianqijiuyun-latiao@users.noreply.github.com> Date: Wed, 24 Jun 2026 10:14:22 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(sidebar):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E8=A7=86=E5=9B=BE=E5=85=83=E6=95=B0=E6=8D=AE=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E5=AF=BC=E8=87=B4=E4=BE=A7=E8=BE=B9=E6=A0=8F=E6=A0=91?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E9=94=99=E4=B9=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MySQL 视图元数据缺失 schema 时回填当前数据库 - 避免多条回退查询生成重复视图节点 - 补充侧边栏视图去重回归测试 --- .../sidebar/sidebarMetadataLoaders.test.ts | 42 ++++++++++++++++++- frontend/src/utils/sidebarMetadata.test.ts | 7 ++++ frontend/src/utils/sidebarMetadata.ts | 7 +++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/sidebar/sidebarMetadataLoaders.test.ts b/frontend/src/components/sidebar/sidebarMetadataLoaders.test.ts index a26252e..c591239 100644 --- a/frontend/src/components/sidebar/sidebarMetadataLoaders.test.ts +++ b/frontend/src/components/sidebar/sidebarMetadataLoaders.test.ts @@ -1,10 +1,17 @@ -import { describe, expect, it, vi } from "vitest"; +import { beforeEach, describe, expect, it, vi } from "vitest"; vi.mock("../../../wailsjs/go/app/App", () => ({ DBQuery: vi.fn(), })); -import { buildSchemasMetadataQuerySpecs } from "./sidebarMetadataLoaders"; +import { DBQuery } from "../../../wailsjs/go/app/App"; +import { buildSchemasMetadataQuerySpecs, loadViews } from "./sidebarMetadataLoaders"; + +const mockedDBQuery = vi.mocked(DBQuery); + +beforeEach(() => { + mockedDBQuery.mockReset(); +}); describe("buildSchemasMetadataQuerySpecs", () => { it("returns schema queries for independent-schema targets", () => { @@ -25,4 +32,35 @@ describe("buildSchemasMetadataQuerySpecs", () => { it("keeps unsupported dialects empty", () => { expect(buildSchemasMetadataQuerySpecs("mysql", "app")).toEqual([]); }); + + it("deduplicates MySQL view metadata when fallback queries omit schema names", async () => { + mockedDBQuery.mockImplementation(async (_config: unknown, _dbName: string, sql: string) => { + if (sql.includes("information_schema.views")) { + return { + success: true, + data: [{ view_name: "CHARACTER_SETS", schema_name: "information_schema" }], + }; + } + if (sql.includes("information_schema.tables")) { + return { + success: true, + data: [{ view_name: "CHARACTER_SETS", schema_name: "information_schema", table_type: "SYSTEM VIEW" }], + }; + } + if (sql.includes("SHOW FULL TABLES FROM `information_schema` WHERE Table_type = 'VIEW'")) { + return { + success: true, + data: [{ Tables_in_information_schema: "CHARACTER_SETS", Table_type: "VIEW" }], + }; + } + return { success: false, data: [] }; + }); + + const result = await loadViews({ config: { type: "mysql" } }, "information_schema"); + + expect(result.supported).toBe(true); + expect(result.views).toEqual([ + { viewName: "CHARACTER_SETS", schemaName: "information_schema" }, + ]); + }); }); diff --git a/frontend/src/utils/sidebarMetadata.test.ts b/frontend/src/utils/sidebarMetadata.test.ts index b09107a..b99ece8 100644 --- a/frontend/src/utils/sidebarMetadata.test.ts +++ b/frontend/src/utils/sidebarMetadata.test.ts @@ -24,6 +24,13 @@ describe('sidebarMetadata', () => { }); }); + it('falls back to the current database when MySQL-compatible view rows omit schema metadata', () => { + expect(normalizeSidebarViewMetadataEntry('mysql', 'information_schema', '', 'CHARACTER_SETS')).toEqual({ + viewName: 'CHARACTER_SETS', + schemaName: 'information_schema', + }); + }); + it('uses MySQL metadata queries for custom MySQL-compatible domestic drivers', () => { expect(resolveSidebarMetadataDialect('goldendb')).toBe('mysql'); expect(resolveSidebarMetadataDialect('custom', 'gdb')).toBe('mysql'); diff --git a/frontend/src/utils/sidebarMetadata.ts b/frontend/src/utils/sidebarMetadata.ts index c971afe..2b7beb5 100644 --- a/frontend/src/utils/sidebarMetadata.ts +++ b/frontend/src/utils/sidebarMetadata.ts @@ -78,9 +78,14 @@ export const normalizeSidebarViewMetadataEntry = ( const parsedViewName = splitQualifiedNameLast(viewName); const parsedNormalizedViewName = splitQualifiedNameLast(normalizedViewName); + const normalizedDialect = String(dialect || '').trim().toLowerCase(); + const normalizedDbName = String(dbName || '').trim(); + const resolvedSchemaName = String( + schemaName || parsedNormalizedViewName.parentPath || parsedViewName.parentPath || '', + ).trim(); return { viewName: normalizedViewName, - schemaName: String(schemaName || parsedNormalizedViewName.parentPath || parsedViewName.parentPath || '').trim(), + schemaName: resolvedSchemaName || (normalizedDialect === 'mysql' ? normalizedDbName : ''), }; };