From c3c4efc6eca9b51139d73dc5d2f34ae62944cbc3 Mon Sep 17 00:00:00 2001 From: Syngnat <92659908+Syngnat@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:07:31 +0800 Subject: [PATCH 1/2] fix(query-result): avoid not-counted summary for auto limit cap --- frontend/src/utils/queryResultPagination.ts | 29 +++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/frontend/src/utils/queryResultPagination.ts b/frontend/src/utils/queryResultPagination.ts index 69f574a9..2a3ead09 100644 --- a/frontend/src/utils/queryResultPagination.ts +++ b/frontend/src/utils/queryResultPagination.ts @@ -22,6 +22,14 @@ const normalizePositiveInteger = (value: unknown): number => { return Number.isFinite(parsed) && parsed > 0 ? parsed : 0; }; +const normalizeSqlForComparison = (sql: string): string => ( + String(sql || '') + .replace(/\s+/g, ' ') + .replace(/;+\s*$/g, '') + .trim() + .toLowerCase() +); + const parseTopLevelLimit = (sql: string): LimitInfo | null => { const { main } = splitSqlTail(sql); const limitPos = findTopLevelKeyword(main, 'limit'); @@ -60,6 +68,14 @@ const stripExplicitLimitForExport = (sql: string): string => { return splitSqlTail(sql).main.trim(); }; +const wasLimitAppliedByQueryEditorCap = (executedSql: string, exportSql: string): boolean => { + const executed = String(executedSql || '').trim(); + const exportable = String(exportSql || '').trim(); + if (!executed || !exportable) return false; + if (normalizeSqlForComparison(executed) === normalizeSqlForComparison(exportable)) return false; + return normalizeSqlForComparison(stripExplicitLimitForExport(executed)) === normalizeSqlForComparison(stripExplicitLimitForExport(exportable)); +}; + const resolveWrappedBaseSql = (dbType: string, baseSql: string): string => { const normalizedType = String(dbType || '').trim().toLowerCase(); const base = baseSql.trim(); @@ -146,11 +162,14 @@ export const createInitialQueryResultPagination = (params: { const exportAllSql = exportSql && getLeadingKeyword(exportSql) === 'select' ? stripExplicitLimitForExport(exportSql) : stripExplicitLimitForExport(executedSql); - const totalState = resolveQueryResultPaginationTotal({ - current, - pageSize, - rowCount: returnedRowCount, - }); + const autoLimitCap = current === 1 && wasLimitAppliedByQueryEditorCap(executedSql, exportSql); + const totalState = autoLimitCap + ? { total: returnedRowCount, totalKnown: true } + : resolveQueryResultPaginationTotal({ + current, + pageSize, + rowCount: returnedRowCount, + }); return { current, From c27a038fc5905508498b87bfbc04a9bdf1b51a53 Mon Sep 17 00:00:00 2001 From: Syngnat <92659908+Syngnat@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:08:03 +0800 Subject: [PATCH 2/2] test(query-result): auto limit cap has exact page total --- .../src/utils/queryResultPagination.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/frontend/src/utils/queryResultPagination.test.ts b/frontend/src/utils/queryResultPagination.test.ts index e84c152d..cff1e8f2 100644 --- a/frontend/src/utils/queryResultPagination.test.ts +++ b/frontend/src/utils/queryResultPagination.test.ts @@ -26,6 +26,25 @@ describe('queryResultPagination', () => { }); }); + it('treats query-editor injected LIMIT as a capped page rather than an uncounted total', () => { + const page = createInitialQueryResultPagination({ + executedSql: 'SELECT id, name FROM users LIMIT 500', + exportSql: 'SELECT id, name FROM users', + dbType: 'mysql', + returnedRowCount: 500, + fallbackPageSize: 500, + }); + + expect(page).toMatchObject({ + current: 1, + pageSize: 500, + total: 500, + totalKnown: true, + baseSql: 'SELECT id, name FROM users', + exportAllSql: 'SELECT id, name FROM users', + }); + }); + it('builds the next page SQL with one lookahead row', () => { expect(buildQueryResultPageSql({ baseSql: 'SELECT id FROM users',