From e2f53a786fc26d08cce0d2a80fd96a9678e111a2 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Mon, 13 Jul 2026 20:13:03 +0800 Subject: [PATCH] fix(grid): inherit timeout for row counts --- apps/desktop/src/components/grid/DataGrid.vue | 5 ++-- .../src/lib/dataGrid/dataGridQueryOptions.ts | 14 +++++++++++ .../app-tests/dataGridQueryOptions.test.ts | 24 +++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 apps/desktop/src/lib/dataGrid/dataGridQueryOptions.ts create mode 100644 packages/app-tests/dataGridQueryOptions.test.ts diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index b717791b62..0cdce71602 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -159,6 +159,7 @@ import { temporalCellEditorConfig, type TemporalCellEditorConfig } from "@/lib/d import { isCancelSearchShortcut, isCopyCurrentRowShortcut, isDeleteCurrentRowShortcut, isFocusSearchShortcut, isModRShortcut, isSaveShortcut, isToggleTransposeShortcut } from "@/lib/editor/keyboardShortcuts"; import { dataGridHeaderContentWidth, scrollbarGutterWidth } from "@/lib/dataGrid/dataGridScrollGutter"; import { canGoNextDataGridPage } from "@/lib/dataGrid/dataGridPagination"; +import { dataGridCountQueryOptions } from "@/lib/dataGrid/dataGridQueryOptions"; import { dataGridBottomScrollTop, dataGridScrollPosition, isDataGridAtScrollBottom, isDataGridNearScrollBottom, shouldCheckInfiniteScrollAfterScroll, type DataGridScrollPosition } from "@/lib/dataGrid/dataGridInfiniteScroll"; import { CANVAS_DATA_GRID_ROW_HEIGHT, drawCanvasDataGrid } from "@/lib/dataGrid/canvasDataGridRenderer"; import { dataGridSaveActionMode, dataGridSaveToolbarState } from "@/lib/dataGrid/dataGridSaveUi"; @@ -3940,7 +3941,7 @@ async function lastPage() { const sql = countTarget?.sql; if (!sql) return; try { - const result = await api.executeQuery(props.connectionId, props.executionDatabase ?? props.database ?? "", sql, countTarget.schema); + const result = await api.executeQuery(props.connectionId, props.executionDatabase ?? props.database ?? "", sql, countTarget.schema, undefined, dataGridCountQueryOptions(connectionStore.getConfig(props.connectionId))); const total = Number(result.rows?.[0]?.[0] ?? 0); if (total <= 0) return; const lastPageNum = Math.ceil(total / pageSize.value); @@ -3975,7 +3976,7 @@ async function calculateTotalRowCount() { try { const countTarget = await buildCurrentCountTarget(); if (!countTarget?.sql) return; - const result = await api.executeQuery(props.connectionId, props.executionDatabase ?? props.database ?? "", countTarget.sql, countTarget.schema); + const result = await api.executeQuery(props.connectionId, props.executionDatabase ?? props.database ?? "", countTarget.sql, countTarget.schema, undefined, dataGridCountQueryOptions(connectionStore.getConfig(props.connectionId))); const total = Number(result.rows?.[0]?.[0] ?? 0); if (Number.isFinite(total) && total >= 0) { manualTotalRowCount.value = total; diff --git a/apps/desktop/src/lib/dataGrid/dataGridQueryOptions.ts b/apps/desktop/src/lib/dataGrid/dataGridQueryOptions.ts new file mode 100644 index 0000000000..fc43d9740d --- /dev/null +++ b/apps/desktop/src/lib/dataGrid/dataGridQueryOptions.ts @@ -0,0 +1,14 @@ +import { queryTimeoutSecsForConnection } from "@/lib/sql/queryTimeout"; +import type { ConnectionConfig } from "@/types/database"; + +export function dataGridCountQueryOptions(connection?: Pick | null): { + maxRows: number; + timeoutSecs: number; +} { + // COUNT queries can be slower than the paged query they summarize. Always + // inherit the connection setting instead of falling back to the backend's shorter legacy default. + return { + maxRows: 1, + timeoutSecs: queryTimeoutSecsForConnection(connection), + }; +} diff --git a/packages/app-tests/dataGridQueryOptions.test.ts b/packages/app-tests/dataGridQueryOptions.test.ts new file mode 100644 index 0000000000..1922c40135 --- /dev/null +++ b/packages/app-tests/dataGridQueryOptions.test.ts @@ -0,0 +1,24 @@ +import assert from "node:assert/strict"; +import { test } from "vitest"; +import { dataGridCountQueryOptions } from "../../apps/desktop/src/lib/dataGrid/dataGridQueryOptions.ts"; + +test("count queries inherit the connection query timeout", () => { + assert.deepEqual(dataGridCountQueryOptions({ query_timeout_secs: 90 }), { + maxRows: 1, + timeoutSecs: 90, + }); +}); + +test("count queries preserve disabled timeouts", () => { + assert.deepEqual(dataGridCountQueryOptions({ query_timeout_secs: 0 }), { + maxRows: 1, + timeoutSecs: 0, + }); +}); + +test("count queries use the frontend default for missing configurations", () => { + assert.deepEqual(dataGridCountQueryOptions(undefined), { + maxRows: 1, + timeoutSecs: 60, + }); +});