fix(grid): preserve result during refresh

This commit is contained in:
t8y2 2026-06-02 18:58:37 +08:00
parent cac90c7b62
commit bce6a820ec
3 changed files with 79 additions and 5 deletions

View File

@ -52,7 +52,7 @@ export function useDataGridActions(activeTab: ComputedRef<QueryTab | undefined>)
const tab = activeTab.value;
if (!tab) return;
queryStore.updateSql(tab.id, sql);
await queryStore.executeTabSql(tab.id, sql);
await queryStore.executeTabSql(tab.id, sql, { preserveResultDuringExecution: true });
}
async function onReloadData(
@ -71,13 +71,17 @@ export function useDataGridActions(activeTab: ComputedRef<QueryTab | undefined>)
const pageOffset = offset ?? 0;
const nextSql = await buildTableSql(tab, { whereInput, orderBy, limit: pageLimit, offset: pageOffset });
queryStore.updateSql(tab.id, nextSql);
await queryStore.executeTabSql(tab.id, nextSql, { pagination: { limit: pageLimit, offset: pageOffset } });
await queryStore.executeTabSql(tab.id, nextSql, {
pagination: { limit: pageLimit, offset: pageOffset },
preserveResultDuringExecution: true,
});
return;
}
if (tab.resultSortedSql) {
await queryStore.executeTabSql(tab.id, tab.resultSortedSql, {
resultBaseSql: tab.resultBaseSql ?? tab.sql,
resultSortedSql: tab.resultSortedSql,
preserveResultDuringExecution: true,
});
return;
}
@ -85,6 +89,7 @@ export function useDataGridActions(activeTab: ComputedRef<QueryTab | undefined>)
await queryStore.executeTabSql(tab.id, sql, {
resultBaseSql: sql,
resultSortedSql: undefined,
preserveResultDuringExecution: true,
});
return;
}
@ -106,6 +111,7 @@ export function useDataGridActions(activeTab: ComputedRef<QueryTab | undefined>)
resultBaseSql: tab.resultBaseSql ?? tab.sql,
resultSortedSql: tab.resultSortedSql,
pagination: { offset, limit, sessionId },
preserveResultDuringExecution: true,
});
return;
}
@ -114,7 +120,10 @@ export function useDataGridActions(activeTab: ComputedRef<QueryTab | undefined>)
tab.whereInput = whereInput ?? "";
const sql = await buildTableSql(tab, { limit, offset, whereInput, orderBy });
queryStore.updateSql(tab.id, sql);
await queryStore.executeTabSql(tab.id, sql, { pagination: { offset, limit } });
await queryStore.executeTabSql(tab.id, sql, {
pagination: { offset, limit },
preserveResultDuringExecution: true,
});
}
async function onSort(column: string, columnIndex: number, direction: "asc" | "desc" | null, whereInput?: string) {
@ -134,7 +143,7 @@ export function useDataGridActions(activeTab: ComputedRef<QueryTab | undefined>)
: undefined;
const sql = await buildTableSql(tab, { orderBy, whereInput });
queryStore.updateSql(tab.id, sql);
await queryStore.executeCurrentTab();
await queryStore.executeTabSql(tab.id, sql, { preserveResultDuringExecution: true });
return;
}
@ -145,6 +154,7 @@ export function useDataGridActions(activeTab: ComputedRef<QueryTab | undefined>)
await queryStore.executeTabSql(tab.id, baseSql, {
resultBaseSql: baseSql,
resultSortedSql: undefined,
preserveResultDuringExecution: true,
});
return;
}
@ -166,6 +176,7 @@ export function useDataGridActions(activeTab: ComputedRef<QueryTab | undefined>)
await queryStore.executeTabSql(tab.id, built.sql, {
resultBaseSql: baseSql,
resultSortedSql: built.sql,
preserveResultDuringExecution: true,
});
}

View File

@ -665,6 +665,7 @@ export const useQueryStore = defineStore("query", () => {
resultSortedSql?: string | undefined;
pagination?: { limit: number; offset: number; sessionId?: string };
mongoSafety?: MongoAggregateSafetyOptions;
preserveResultDuringExecution?: boolean;
},
) {
const tab = tabs.value.find((t) => t.id === id);
@ -680,7 +681,9 @@ export const useQueryStore = defineStore("query", () => {
tab.lastExecutedSql = sql;
tab.resultTotalRowCount = undefined;
const previousResultSessionClose = closeResultSession(tab, options?.pagination?.sessionId);
clearResultPayload(tab);
if (!options?.preserveResultDuringExecution || !tab.result) {
clearResultPayload(tab);
}
console.info("[DBX][executeTabSql:start]", {
traceId,
tabId: id,

View File

@ -496,6 +496,66 @@ test("starting a new query clears the previous result payload immediately", asyn
}
});
test("grid refreshes can preserve the previous result while loading", async () => {
const restoreStorage = installMemoryStorage();
setActivePinia(createPinia());
const connectionStore = useConnectionStore();
const store = useQueryStore();
const originalFetch = globalThis.fetch;
connectionStore.addEphemeralConnection(conn("conn-1"));
const tabId = store.createTab("conn-1", "db", "Query");
const tab = store.tabs.find((item) => item.id === tabId);
assert.ok(tab);
const previousResult: QueryResult = {
columns: ["id", "name"],
rows: [[1, "Ada"]],
affected_rows: 0,
execution_time_ms: 1,
};
tab.result = previousResult;
globalThis.fetch = (async (input) => {
const url = String(input);
if (url === "/api/query/prepare-pagination-plan") {
return new Response(JSON.stringify({ sqlToExecute: "select 1 order by name", useAgentResultSession: false }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}
if (url === "/api/query/execute-multi") {
return new Response(
JSON.stringify([{ columns: ["id", "name"], rows: [[2, "Grace"]], affected_rows: 0, execution_time_ms: 1 }]),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
}
if (url === "/api/query/analyze-editability") {
return new Response(JSON.stringify({ editable: false, reason: "complex-source" }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}
return new Response("unexpected request", { status: 500 });
}) as typeof fetch;
try {
const execution = store.executeTabSql(tabId, "select 1 order by name", {
preserveResultDuringExecution: true,
});
assert.deepEqual(tab.result?.columns, previousResult.columns);
assert.deepEqual(tab.result?.rows, previousResult.rows);
assert.equal(tab.isExecuting, true);
await execution;
assert.deepEqual(tab.result?.rows, [[2, "Grace"]]);
} finally {
globalThis.fetch = originalFetch;
restoreStorage();
}
});
test("data tab execution preserves pagination offset metadata", async () => {
const restoreStorage = installMemoryStorage();
setActivePinia(createPinia());