Merge pull request #708 from virgosgod-maker/fix/data-viewer-refresh-total

This commit is contained in:
Syngnat
2026-07-24 17:36:57 +08:00
2 changed files with 75 additions and 4 deletions

View File

@@ -606,6 +606,58 @@ describe('DataViewer safe editing locator', () => {
renderer!.unmount();
});
it('recounts the known total when table data shrinks after a manual refresh', async () => {
storeState.connections[0].config.type = 'mysql';
storeState.connections[0].config.database = 'main';
backendApp.DBGetColumns.mockResolvedValue({
success: true,
data: [{ name: 'ID', key: 'PRI' }, { name: 'NAME', key: '' }],
});
let countQueryCount = 0;
backendApp.DBQuery.mockImplementation(async (_config: any, _dbName: string, sql: string) => {
if (/count\s*\(/i.test(String(sql))) {
countQueryCount += 1;
return {
success: true,
fields: ['total'],
data: [{ total: countQueryCount === 1 ? 500 : 430 }],
};
}
return {
success: true,
fields: ['ID', 'NAME'],
data: createRows(101),
};
});
let renderer: ReactTestRenderer;
await act(async () => {
renderer = create(<DataViewer tab={createTab({ dbName: 'main', tableName: 'users', title: 'users' })} />);
});
await flushPromises();
expect(dataGridState.latestProps?.pagination).toMatchObject({
total: 500,
totalKnown: true,
});
await act(async () => {
dataGridState.latestProps?.onReload();
await Promise.resolve();
await Promise.resolve();
});
await flushPromises();
expect(countQueryCount).toBe(2);
expect(dataGridState.latestProps?.pagination).toMatchObject({
total: 430,
totalKnown: true,
});
expect(dataGridState.latestProps?.data).toHaveLength(100);
renderer!.unmount();
});
it('shows an actionable message for DuckDB timeout interruption errors', async () => {
storeState.languagePreference = 'en-US';
storeState.connections[0].config.type = 'duckdb';

View File

@@ -583,7 +583,8 @@ const DataViewer: React.FC<{ tab: TabData; isActive?: boolean }> = React.memo(({
setPagination(prev => ({ ...prev, totalCountLoading: false, totalCountCancelled: true }));
}, []);
const fetchData = useCallback(async (page = pagination.current, size = pagination.pageSize) => {
const fetchData = useCallback(async (page = pagination.current, size = pagination.pageSize, options?: { refreshTotal?: boolean }) => {
const refreshTotal = options?.refreshTotal === true;
const seq = ++fetchSeqRef.current;
setLoading(true);
const conn = connections.find(c => c.id === tab.connectionId);
@@ -717,15 +718,16 @@ const DataViewer: React.FC<{ tab: TabData; isActive?: boolean }> = React.memo(({
: buildOrderBySQL(dbType, sortInfo, resolveDataViewerOrderFallbackColumns(editLocatorForQuery, pkColumnsForQuery));
const totalRows = Number(pagination.total);
const hasFiniteTotal = Number.isFinite(totalRows) && totalRows >= 0;
const totalKnown = pagination.totalKnown && hasFiniteTotal;
const totalKnown = !refreshTotal && pagination.totalKnown && hasFiniteTotal;
const approximateTotalRows = Number(pagination.approximateTotal);
const hasApproximateTotalPages =
!refreshTotal &&
!totalKnown &&
supportsApproximateTotalPages &&
pagination.totalApprox &&
Number.isFinite(approximateTotalRows) &&
approximateTotalRows > 0;
const effectiveTotalRows = hasApproximateTotalPages ? approximateTotalRows : totalRows;
const effectiveTotalRows = hasApproximateTotalPages ? approximateTotalRows : (refreshTotal ? 0 : totalRows);
const totalPages = Number.isFinite(effectiveTotalRows) && effectiveTotalRows > 0 ? Math.max(1, Math.ceil(effectiveTotalRows / size)) : 0;
const currentPage = totalPages > 0 ? Math.min(Math.max(1, page), totalPages) : Math.max(1, page);
const offset = (currentPage - 1) * size;
@@ -1141,7 +1143,24 @@ const DataViewer: React.FC<{ tab: TabData; isActive?: boolean }> = React.memo(({
void fetchData(pagination.current, pagination.pageSize);
}, [fetchData, pagination.current, pagination.pageSize]);
const handleReload = useCallback(() => {
fetchData(pagination.current, pagination.pageSize);
countSeqRef.current++;
manualCountSeqRef.current++;
duckdbApproxSeqRef.current++;
oracleApproxSeqRef.current++;
countKeyRef.current = '';
autoCountKeyRef.current = '';
manualCountKeyRef.current = '';
duckdbApproxKeyRef.current = '';
oracleApproxKeyRef.current = '';
setPagination(prev => ({
...prev,
totalKnown: false,
totalApprox: false,
approximateTotal: undefined,
totalCountLoading: false,
totalCountCancelled: false,
}));
fetchData(pagination.current, pagination.pageSize, { refreshTotal: true });
}, [fetchData, pagination.current, pagination.pageSize]);
const handleSort = useCallback((field: string, order: string) => {
// 支持多字段排序field 为 JSON 数组字符串时解析为多字段