From d9018091c762cd33f95dd64ceb6affa23c646a09 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Fri, 31 Jul 2026 01:34:38 +0800 Subject: [PATCH] fix(query): stop unsupported SQL Server page retries --- .../queryStore.hiddenPrimaryKey.spec.ts | 37 +++++++++++++++++++ apps/desktop/src/stores/queryStore.ts | 15 ++++++++ 2 files changed, 52 insertions(+) diff --git a/apps/desktop/src/stores/__tests__/queryStore.hiddenPrimaryKey.spec.ts b/apps/desktop/src/stores/__tests__/queryStore.hiddenPrimaryKey.spec.ts index eb8e571e5..499077d7e 100644 --- a/apps/desktop/src/stores/__tests__/queryStore.hiddenPrimaryKey.spec.ts +++ b/apps/desktop/src/stores/__tests__/queryStore.hiddenPrimaryKey.spec.ts @@ -930,4 +930,41 @@ describe("queryStore hidden primary key editing", () => { await vi.waitFor(() => expect(tab.resultTotalRowCount).toBe(123)); expect(tab.resultTotalRowCountLoading).toBe(false); }); + + it("stops appending when a SQL Server query has no bounded next-page plan", async () => { + getConnectionConfig.mockReturnValue({ id: "sqlserver-1", name: "SQL Server", db_type: "sqlserver", database: "app", query_timeout_secs: 30 }); + analyzeEditableQueryEditability.mockResolvedValue({ editable: false, reason: "complex-query" }); + const rows = Array.from({ length: 28 }, (_, index) => [index + 1]); + executeMulti.mockResolvedValueOnce([ + { + columns: ["id"], + rows, + affected_rows: 28, + execution_time_ms: 1, + has_more: true, + }, + ]); + + const { useQueryStore } = await import("@/stores/queryStore"); + const store = useQueryStore(); + const tabId = store.createTab("sqlserver-1", "app", "Query"); + const sql = "SELECT a.id, b.* FROM orders a JOIN order_details b ON b.order_id = a.id"; + + await store.executeTabSql(tabId, sql); + expect(executeMulti).toHaveBeenCalledTimes(1); + + await store.executeTabSql(tabId, sql, { + resultBaseSql: sql, + pagination: { limit: 25, offset: 28 }, + appendResult: { maxRows: 10_000 }, + preserveResultDuringExecution: true, + preserveTotalRowCountDuringExecution: true, + replaceActiveResultInGroup: true, + }); + + const tab = store.tabs.find((item) => item.id === tabId)!; + expect(executeMulti).toHaveBeenCalledTimes(1); + expect(tab.result?.rows).toEqual(rows); + expect(tab.result?.has_more).toBe(false); + }); }); diff --git a/apps/desktop/src/stores/queryStore.ts b/apps/desktop/src/stores/queryStore.ts index 4a49bd860..6b4f750a0 100644 --- a/apps/desktop/src/stores/queryStore.ts +++ b/apps/desktop/src/stores/queryStore.ts @@ -3850,6 +3850,21 @@ export const useQueryStore = defineStore("query", () => { pageOffset = plan.pageOffset; countSql = plan.countSql; useAgentResultSession = plan.useAgentResultSession; + const hasBoundedPagination = typeof pageLimit === "number" && typeof pageOffset === "number"; + if (options?.appendResult && !hasBoundedPagination && !useAgentResultSession) { + const current = tabs.value.find((item) => item.id === id); + if (current?.executionId === executionId && current.result) { + current.result.has_more = false; + const activeResultIndex = current.activeResultIndex; + if (Array.isArray(current.results) && typeof activeResultIndex === "number" && activeResultIndex >= 0 && activeResultIndex < current.results.length) { + current.results[activeResultIndex]!.has_more = false; + } + touchResult(current); + syncDisplayedResultRun(current, queryBaseSql, openInNewResultTab); + } + queryExecutionLog("info", "append-result:pagination-unsupported", { traceId, elapsed: elapsed() }); + return false; + } } else if (tab.mode === "data") { pageLimit = options?.pagination?.limit ?? tableOpenPageLimit(settingsStore.editorSettings.tableOpenPageSize); pageOffset = options?.pagination?.offset ?? 0;