diff --git a/.github/pr-assets/13266-result-tab-after-click.png b/.github/pr-assets/13266-result-tab-after-click.png new file mode 100644 index 0000000000..73012c9a57 Binary files /dev/null and b/.github/pr-assets/13266-result-tab-after-click.png differ diff --git a/.github/pr-assets/13266-result-tab-tooltip-after.png b/.github/pr-assets/13266-result-tab-tooltip-after.png new file mode 100644 index 0000000000..fe06de29c0 Binary files /dev/null and b/.github/pr-assets/13266-result-tab-tooltip-after.png differ diff --git a/.github/pr-assets/13266-result-tab-tooltip-before.png b/.github/pr-assets/13266-result-tab-tooltip-before.png new file mode 100644 index 0000000000..c22db7b25e Binary files /dev/null and b/.github/pr-assets/13266-result-tab-tooltip-before.png differ diff --git a/apps/desktop/src/lib/__tests__/tabs/tabPresentation.spec.ts b/apps/desktop/src/lib/__tests__/tabs/tabPresentation.spec.ts index 441aec3a91..1f3230e2bf 100644 --- a/apps/desktop/src/lib/__tests__/tabs/tabPresentation.spec.ts +++ b/apps/desktop/src/lib/__tests__/tabs/tabPresentation.spec.ts @@ -188,6 +188,38 @@ describe("query result labels", () => { expect(item?.title).toBe("SELECT 1"); }); + it("bounds the SQL fallback tooltip for results without a source object", () => { + const longSql = `SELECT * FROM (${Array.from({ length: 40 }, (_, i) => `SELECT ${i + 1} AS value`).join(" UNION ALL ")}) AS combined`; + const [item] = tabularResultItems([ + { + columns: ["value"], + rows: [[1]], + affected_rows: 0, + execution_time_ms: 1, + sourceStatement: longSql, + }, + ]); + + const expected = `${longSql.replace(/\s+/g, " ").trim().slice(0, 160)}…`; + expect(item?.label).toBeUndefined(); + expect(item?.title).toBe(expected); + expect(item?.title!.length).toBe(161); + }); + + it("collapses multiline SQL fallback tooltips onto a single line", () => { + const [item] = tabularResultItems([ + { + columns: ["id"], + rows: [[1]], + affected_rows: 0, + execution_time_ms: 1, + sourceStatement: "SELECT *\n FROM (SELECT id\n FROM users)", + }, + ]); + + expect(item?.title).toBe("SELECT * FROM (SELECT id FROM users)"); + }); + it("shows only the object name when result set names exclude the database", () => { const results = [ { diff --git a/apps/desktop/src/lib/tabs/tabPresentation.ts b/apps/desktop/src/lib/tabs/tabPresentation.ts index 669c042d45..2726c2ba54 100644 --- a/apps/desktop/src/lib/tabs/tabPresentation.ts +++ b/apps/desktop/src/lib/tabs/tabPresentation.ts @@ -463,6 +463,14 @@ export function middleEllipsis(value: string, maxLength = 24): string { return `${value.slice(0, startLength)}...${end}`; } +// 无来源对象的结果(如外层 SELECT * FROM (...) 包装查询)页签 tooltip 会回退到 SQL 文本; +// 整条语句会把浮层撑成遮挡工作区的巨块并拦截点击,这里折叠空白并限制长度 (#13266) +export function sourceStatementTooltip(statement: string | undefined, maxLength = 160): string | undefined { + const singleLine = statement?.replace(/\s+/g, " ").trim(); + if (!singleLine) return undefined; + return singleLine.length > maxLength ? `${singleLine.slice(0, maxLength)}…` : singleLine; +} + export function resultSqlForGrid(tab: Pick): string { return tab.result?.sourceStatement || tab.resultBaseSql || tab.lastExecutedSql || tab.sql; } @@ -602,7 +610,7 @@ export function tabularResultItems(results: QueryResult[] | undefined, options: label: displaySource, displayLabel, labelTruncated: !!displaySource && displayLabel !== displaySource, - title: item.result.sourceLabel || item.result.sourceStatement, + title: item.result.sourceLabel || sourceStatementTooltip(item.result.sourceStatement), }; }); }