diff --git a/src/i18n/locales/de.json b/src/i18n/locales/de.json index 2c71b48c..b2997df9 100644 --- a/src/i18n/locales/de.json +++ b/src/i18n/locales/de.json @@ -850,6 +850,7 @@ "page": "Seite {{current}}", "jumpToPage": "Klicken, um zur Seite zu springen", "loadRowCount": "Zeilenanzahl laden", + "rowCount": "{{total}} Zeilen", "executePrompt": "Führe eine Abfrage aus, um Ergebnisse zu sehen", "results": { "minimize": "Minimieren", diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 85fb24fc..9a3de3a4 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -866,6 +866,7 @@ "page": "Page {{current}}", "jumpToPage": "Click to jump to page", "loadRowCount": "Load row count", + "rowCount": "{{total}} rows", "executePrompt": "Execute a query to see results", "tableRunPrompt": "Press Run (Ctrl/Command+F5) to load table data", "results": { diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json index ac679ce7..ff20ec5e 100644 --- a/src/i18n/locales/es.json +++ b/src/i18n/locales/es.json @@ -849,6 +849,7 @@ "page": "Página {{current}}", "jumpToPage": "Clic para ir a la página", "loadRowCount": "Cargar conteo de filas", + "rowCount": "{{total}} filas", "executePrompt": "Ejecuta una consulta para ver resultados", "results": { "minimize": "Minimizar", diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index 2420cb4f..9f4b1057 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -850,6 +850,7 @@ "page": "Page {{current}}", "jumpToPage": "Cliquer pour aller à la page", "loadRowCount": "Charger le nombre de lignes", + "rowCount": "{{total}} lignes", "executePrompt": "Exécutez une requête pour voir les résultats", "results": { "minimize": "Réduire", diff --git a/src/i18n/locales/it.json b/src/i18n/locales/it.json index 5b7df5ff..472f5e81 100644 --- a/src/i18n/locales/it.json +++ b/src/i18n/locales/it.json @@ -833,6 +833,7 @@ "page": "Pagina {{current}}", "jumpToPage": "Clicca per saltare alla pagina", "loadRowCount": "Carica conteggio righe", + "rowCount": "{{total}} righe", "executePrompt": "Esegui una query per vedere i risultati", "tableRunPrompt": "Premi Esegui (Ctrl/Command+F5) per caricare i dati della tabella", "results": { diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json index 9914178f..73e0a9df 100644 --- a/src/i18n/locales/ja.json +++ b/src/i18n/locales/ja.json @@ -863,6 +863,7 @@ "page": "{{current}} ページ", "jumpToPage": "クリックでページ移動", "loadRowCount": "行数を読み込む", + "rowCount": "{{total}} 行", "executePrompt": "クエリを実行すると結果が表示されます", "results": { "minimize": "最小化", diff --git a/src/i18n/locales/ru.json b/src/i18n/locales/ru.json index 54cc92ab..6b04953f 100644 --- a/src/i18n/locales/ru.json +++ b/src/i18n/locales/ru.json @@ -845,6 +845,7 @@ "page": "Страница {{current}}", "jumpToPage": "Нажмите для перехода на страницу", "loadRowCount": "Загрузить количество строк", + "rowCount": "{{total}} строк", "executePrompt": "Выполните запрос, чтобы увидеть результаты", "results": { "minimize": "Свернуть", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index 059d7dfb..6a15190e 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -818,6 +818,7 @@ "page": "第 {{current}} 页", "jumpToPage": "点击跳转到页面", "loadRowCount": "加载行数", + "rowCount": "{{total}} 行", "executePrompt": "执行查询以查看结果", "results": { "minimize": "最小化", diff --git a/src/pages/Editor.tsx b/src/pages/Editor.tsx index 26cfc6e2..dbe8b9f0 100644 --- a/src/pages/Editor.tsx +++ b/src/pages/Editor.tsx @@ -439,6 +439,9 @@ export const Editor = () => { const tabsRef = useRef([]); const activeTabIdRef = useRef(null); + // Last executed SQL per tab — used to preserve the loaded row count across + // pagination of the SAME query while resetting it when the query changes. + const lastRunQueryRef = useRef>({}); // Stable refs for functions used inside Monaco actions (which capture closures at mount time) const runQueryRef = useRef(null!); const runMultipleQueriesRef = useRef(null!); @@ -772,10 +775,13 @@ export const Editor = () => { } } + const isSameQuery = lastRunQueryRef.current[targetTabId] === textToRun; + lastRunQueryRef.current[targetTabId] = textToRun; const resultWithCount = res.pagination && res.pagination.total_rows === null && - previousTotalRows !== null + previousTotalRows !== null && + isSameQuery ? { ...res, pagination: { @@ -1107,6 +1113,20 @@ export const Editor = () => { ? tabsRef.current.find((t) => t.id === tabIdArg) : activeTab; if (!tab?.result?.pagination || !activeConnectionId) return; + // Count the reconstructed filtered query, not tab.query (which omits the + // filter box's WHERE); LIMIT is dropped so it can't cap the count. + const countTarget = + tab.type === "table" && tab.activeTable + ? reconstructTableQuery( + { + ...tab, + schema: + activeCapabilities?.schemas === true ? tab.schema : undefined, + }, + activeDriver ?? undefined, + { sortOverride: null, limitOverride: null }, + ) + : tab.query; // setIsCountLoading drives the spinner in the main window only; skip it for // a count triggered from a detached window (its own window owns its spinner). const isDetached = detachedTabIdsRef.current.has(tab.id); @@ -1114,7 +1134,7 @@ export const Editor = () => { try { const total = await invoke("count_query", { connectionId: activeConnectionId, - query: tab.query, + query: countTarget, schema: tab.schema ?? activeSchema, }); const latest = tabsRef.current.find((t) => t.id === tab.id) ?? tab; @@ -1129,7 +1149,14 @@ export const Editor = () => { if (!isDetached) setIsCountLoading(false); } }, - [activeTab, activeConnectionId, activeSchema, updateTab], + [ + activeTab, + activeConnectionId, + activeSchema, + activeDriver, + activeCapabilities?.schemas, + updateTab, + ], ); // --- Detached results windows (one per detached tab) --- @@ -3557,8 +3584,7 @@ export const Editor = () => { )} - {/* Count load button or spinner */} - {activeTab.result.pagination.total_rows === null && ( + {activeTab.result.pagination.total_rows === null ? ( + ) : ( + + {t("editor.rowCount", { + total: + activeTab.result.pagination.total_rows.toLocaleString(), + })} + )}