diff --git a/apps/desktop/src/stores/queryStore.ts b/apps/desktop/src/stores/queryStore.ts index f0da38081a..292f6a9fdd 100644 --- a/apps/desktop/src/stores/queryStore.ts +++ b/apps/desktop/src/stores/queryStore.ts @@ -5256,7 +5256,7 @@ export const useQueryStore = defineStore("query", () => { return producedResult; } - const queryResultMaxRows = effectiveQueryResultMaxRows(settingsStore.editorSettings.queryResultMaxRowsEnabled, settingsStore.editorSettings.queryResultMaxRows); + const queryResultMaxRows = tab.mode === "query" ? effectiveQueryResultMaxRows(settingsStore.editorSettings.queryResultMaxRowsEnabled, settingsStore.editorSettings.queryResultMaxRows) : undefined; if (tab.mode === "query") { const prepared = await prepareEditableQueryExecution(tab, sqlToExecute, conn, effectiveDbType, executionDatabase, traceId, elapsed); diff --git a/packages/app-tests/dataGridPagination.test.ts b/packages/app-tests/dataGridPagination.test.ts index 8681b96161..40b85ecf47 100644 --- a/packages/app-tests/dataGridPagination.test.ts +++ b/packages/app-tests/dataGridPagination.test.ts @@ -62,6 +62,28 @@ test("exact display totals keep pagination inside the configured result cap", () ); }); +test("large table pagination keeps the real last page and deep page offset", () => { + const totalRows = 3_374_023; + const pageSize = 100; + const tablePaginationTotal = resolveDataGridPaginationTotal({ + serverKnownTotalRowCount: totalRows, + totalRowCountIsExact: true, + }); + const queryPaginationTotal = resolveDataGridPaginationTotal({ + serverKnownTotalRowCount: totalRows, + totalRowCountIsExact: true, + maxRows: 100_000, + }); + + assert.equal(tablePaginationTotal, totalRows); + assert.equal(queryPaginationTotal, 100_000); + + const lastPage = Math.max(1, Math.ceil((tablePaginationTotal ?? 0) / pageSize)); + assert.equal(lastPage, 33_741); + assert.equal((lastPage - 1) * pageSize, 3_374_000); + assert.equal((2_000 - 1) * pageSize, 199_900); +}); + test("first query page is complete when its known total is already loaded", () => { assert.equal( hasCompleteLocalDataGridResult({ diff --git a/packages/app-tests/queryStore.test.ts b/packages/app-tests/queryStore.test.ts index fb95aa481a..75524840b2 100644 --- a/packages/app-tests/queryStore.test.ts +++ b/packages/app-tests/queryStore.test.ts @@ -7729,6 +7729,52 @@ test("data tab execution uses a tab-scoped client session", async () => { } }); +test("table-data pagination is not clamped by the query result row cap", async () => { + const restoreStorage = installMemoryStorage(); + setActivePinia(createPinia()); + const connectionStore = useConnectionStore(); + const settingsStore = useSettingsStore(); + const store = useQueryStore(); + const originalFetch = globalThis.fetch; + let executeBody: any; + + settingsStore.updateEditorSettings({ queryResultMaxRowsEnabled: true, queryResultMaxRows: 100_000 }); + connectionStore.addEphemeralConnection(conn("table-data-deep-page")); + const tabId = store.createTab("table-data-deep-page", "db", "users", "data", "public"); + const tab = store.tabs.find((item) => item.id === tabId); + assert.ok(tab); + + globalThis.fetch = withConnectionHealthMock(async (input, init) => { + if (String(input) !== "/api/query/execute-multi") return new Response("unexpected request", { status: 500 }); + executeBody = JSON.parse(String(init?.body ?? "{}")); + return Response.json([ + { + columns: ["id"], + rows: Array.from({ length: 100 }, (_, index) => [199_901 + index]), + affected_rows: 0, + execution_time_ms: 1, + }, + ]); + }); + + try { + await store.executeTabSql(tabId, 'SELECT * FROM "users" LIMIT 100 OFFSET 199900', { + pagination: { limit: 100, offset: 199_900 }, + }); + + assert.match(executeBody.sql, /OFFSET 199900/); + assert.equal(executeBody.maxRows, 100); + assert.equal(executeBody.fetchSize, 100); + assert.equal(tab.resultPageLimit, 100); + assert.equal(tab.resultPageOffset, 199_900); + assert.equal(tab.result?.truncated, undefined); + assert.equal(tab.resultTotalRowCount, undefined); + } finally { + globalThis.fetch = originalFetch; + restoreStorage(); + } +}); + test("closing a data tab releases its tab-scoped client session", async () => { const restoreStorage = installMemoryStorage(); setActivePinia(createPinia());