feat(grid): add pinned query result history
This commit is contained in:
parent
fe39a38dd4
commit
c155443d4b
|
|
@ -2,7 +2,7 @@
|
|||
import { computed, ref, defineAsyncComponent, watch, nextTick, onMounted, onUnmounted } from "vue";
|
||||
import type { CSSProperties } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { Check, Columns3, Loader2, Search, Bot, GitBranch, BarChart3, TableProperties, ChevronDown, ChevronUp, Inbox, RefreshCcw, Wrench, Toolbox, ListChecks, Database, FileUp, Download, X } from "@lucide/vue";
|
||||
import { Check, Columns3, Loader2, Search, Bot, GitBranch, BarChart3, TableProperties, ChevronDown, ChevronUp, Inbox, RefreshCcw, Wrench, Toolbox, ListChecks, Database, FileUp, Download, X, Pin } from "@lucide/vue";
|
||||
import { Splitpanes, Pane } from "splitpanes";
|
||||
import "splitpanes/dist/splitpanes.css";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
@ -230,9 +230,11 @@ const activeQueryError = computed(() => {
|
|||
const hasQueryOutput = computed(() => !!props.activeTab.result || !!props.activeTab.explainPlan || !!props.activeTab.explainError || props.activeTab.isExecuting === true || props.activeTab.isExplaining === true);
|
||||
const tabularResults = computed(() => tabularResultItems(props.activeTab.results));
|
||||
const resultRuns = computed(() => resultRunItems(props.activeTab));
|
||||
const activeResultRunItem = computed(() => resultRuns.value.find((run) => run.active));
|
||||
const activeResultGridCacheKey = computed(() => resultGridCacheKey(props.activeTab));
|
||||
const resultArchiveExporting = ref(false);
|
||||
const canExportResultArchive = computed(() => props.activeTab.mode === "query" && (!!props.activeTab.result || !!props.activeTab.results?.length || !!props.activeTab.resultRuns?.length));
|
||||
const resultAutoSave = computed(() => props.activeTab.resultAutoSave === true);
|
||||
watch(
|
||||
() => tabularResults.value.map((item) => item.index).join(","),
|
||||
() => {
|
||||
|
|
@ -482,6 +484,19 @@ function removeResultRun(runId: string) {
|
|||
if (removed && removedActiveRun) emit("update:activeOutputView", "result");
|
||||
}
|
||||
|
||||
async function selectResultRun(runId: string) {
|
||||
if (!(await queryStore.setActiveResultRun(props.activeTab.id, runId))) {
|
||||
toast(t("tabs.missingResultRun"), 4000);
|
||||
return;
|
||||
}
|
||||
emit("update:activeOutputView", "result");
|
||||
}
|
||||
|
||||
function toggleResultAutoSave() {
|
||||
const enabled = queryStore.toggleResultAutoSave(props.activeTab.id);
|
||||
toast(t(enabled ? "tabs.autoKeepResultsEnabled" : "tabs.autoKeepResultsDisabled"), 2500);
|
||||
}
|
||||
|
||||
function handleModRTarget(target: Element): boolean {
|
||||
if (target.closest("[data-query-editor-root]")) return queryEditorRef.value?.openReplace() ?? false;
|
||||
if (target.closest("[data-cell-detail-editor-root]")) return dataGridRef.value?.openCellDetailSearch() ?? false;
|
||||
|
|
@ -545,26 +560,45 @@ defineExpose({ focusSearch, refreshData, handleModRTarget });
|
|||
{{ t("tabs.tableData") }}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
v-if="activeTab.mode === 'query' && activeTab.result"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class="h-6 w-7 shrink-0 text-muted-foreground hover:text-foreground"
|
||||
:class="{ 'text-primary': resultAutoSave }"
|
||||
:title="resultAutoSave ? t('tabs.autoKeepResultsEnabled') : t('tabs.autoKeepResults')"
|
||||
:aria-label="resultAutoSave ? t('tabs.autoKeepResultsEnabled') : t('tabs.autoKeepResults')"
|
||||
:aria-pressed="resultAutoSave"
|
||||
@click="toggleResultAutoSave"
|
||||
>
|
||||
<Pin class="h-3.5 w-3.5" :class="{ 'fill-current': resultAutoSave }" />
|
||||
</Button>
|
||||
<template v-if="resultRuns.length > 0">
|
||||
<span class="mx-1 h-4 w-px shrink-0 bg-border" />
|
||||
<div class="flex min-w-0 max-w-[35%] items-center gap-1 overflow-x-auto overflow-y-hidden px-1" :aria-label="t('tabs.resultRuns')">
|
||||
<div v-for="run in resultRuns" :key="run.id" class="inline-flex shrink-0 items-center">
|
||||
<Button
|
||||
size="sm"
|
||||
:variant="run.active ? 'default' : 'ghost'"
|
||||
class="h-6 rounded-r-none px-2 text-xs"
|
||||
@click="
|
||||
queryStore.setActiveResultRun(activeTab.id, run.id);
|
||||
emit('update:activeOutputView', 'result');
|
||||
"
|
||||
>
|
||||
{{ t("tabs.runN", { n: run.sequence }) }}
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="ghost" size="sm" class="h-6 shrink-0 gap-1 px-2 text-xs">
|
||||
{{ activeResultRunItem ? t("tabs.runN", { n: activeResultRunItem.sequence }) : t("tabs.resultRuns") }}
|
||||
<ChevronDown class="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
<Button size="icon" :variant="run.active ? 'default' : 'ghost'" class="h-6 w-6 rounded-l-none border-l border-border/50 px-0" :title="t('tabs.removeRun', { n: run.sequence })" :aria-label="t('tabs.removeRun', { n: run.sequence })" @click.stop="removeResultRun(run.id)">
|
||||
<X class="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" class="w-48">
|
||||
<DropdownMenuItem v-for="run in resultRuns" :key="run.id" class="flex items-center gap-2 pr-1" @select="selectResultRun(run.id)">
|
||||
<Check v-if="run.active" class="h-3.5 w-3.5 shrink-0" />
|
||||
<span v-else class="h-3.5 w-3.5 shrink-0" />
|
||||
<span class="min-w-0 flex-1 truncate">{{ t("tabs.runN", { n: run.sequence }) }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-sm text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
:title="t('tabs.removeRun', { n: run.sequence })"
|
||||
:aria-label="t('tabs.removeRun', { n: run.sequence })"
|
||||
@click.stop.prevent="removeResultRun(run.id)"
|
||||
>
|
||||
<X class="h-3 w-3" />
|
||||
</button>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
<template v-if="tabularResults.length > 1">
|
||||
<span class="mx-1 h-4 w-px shrink-0 bg-border" />
|
||||
|
|
|
|||
|
|
@ -453,6 +453,9 @@ export default {
|
|||
runN: "Run {n}",
|
||||
resultRuns: "Result runs",
|
||||
removeRun: "Remove run {n}",
|
||||
autoKeepResults: "Auto-keep query results",
|
||||
autoKeepResultsEnabled: "Auto-keep results enabled",
|
||||
autoKeepResultsDisabled: "Auto-keep results disabled",
|
||||
missingResultRun: "This result is no longer available",
|
||||
exportResultArchive: "Export Results",
|
||||
importResultArchive: "Import Results",
|
||||
|
|
|
|||
|
|
@ -452,6 +452,9 @@ export default {
|
|||
runN: "実行 {n}",
|
||||
resultRuns: "実行履歴",
|
||||
removeRun: "実行 {n} を削除",
|
||||
autoKeepResults: "クエリ結果を自動保持",
|
||||
autoKeepResultsEnabled: "結果の自動保持をオンにしました",
|
||||
autoKeepResultsDisabled: "結果の自動保持をオフにしました",
|
||||
missingResultRun: "この結果は利用できなくなりました",
|
||||
exportResultArchive: "結果をエクスポート",
|
||||
importResultArchive: "結果をインポート",
|
||||
|
|
|
|||
|
|
@ -454,6 +454,9 @@ export default {
|
|||
runN: "执行 {n}",
|
||||
resultRuns: "执行结果",
|
||||
removeRun: "删除执行 {n}",
|
||||
autoKeepResults: "自动保留查询结果",
|
||||
autoKeepResultsEnabled: "已开启自动保留结果",
|
||||
autoKeepResultsDisabled: "已关闭自动保留结果",
|
||||
missingResultRun: "此结果已不可用",
|
||||
exportResultArchive: "导出结果",
|
||||
importResultArchive: "导入结果",
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ export interface SavedOpenTab {
|
|||
resultCacheKey?: string;
|
||||
resultRuns?: SavedQueryResultRun[];
|
||||
activeResultRunId?: string;
|
||||
resultAutoSave?: boolean;
|
||||
}
|
||||
|
||||
export interface RestoredOpenTabs {
|
||||
|
|
@ -92,6 +93,7 @@ export function serializeOpenTabs(tabs: QueryTab[]): SavedOpenTab[] {
|
|||
}
|
||||
: {}),
|
||||
...(tab.mode === "query" && tab.activeResultRunId !== undefined ? { activeResultRunId: tab.activeResultRunId } : {}),
|
||||
...(tab.mode === "query" && tab.resultAutoSave ? { resultAutoSave: true } : {}),
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -135,6 +137,7 @@ export function restoreOpenTabsState(rawTabs: string | null, rawActiveTabId: str
|
|||
resultCacheState: mode !== "data" && tab.resultCacheKey ? "disk" : undefined,
|
||||
resultRuns,
|
||||
activeResultRunId: resultRuns?.some((run) => run.id === tab.activeResultRunId) ? tab.activeResultRunId : resultRuns?.[0]?.id,
|
||||
resultAutoSave: mode === "query" && tab.resultAutoSave ? true : undefined,
|
||||
};
|
||||
});
|
||||
const activeTabId = rawActiveTabId || null;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ const STORAGE_KEY = "dbx-open-tabs";
|
|||
const ACTIVE_TAB_KEY = "dbx-active-tab";
|
||||
const ORACLE_LIKE_METADATA_TYPES = new Set<string>(["oracle", "dameng", "oceanbase-oracle"]);
|
||||
|
||||
function resultRunCacheKey(tabId: string, runId: string): string {
|
||||
return `tab:${tabId}:run:${runId}`;
|
||||
}
|
||||
|
||||
function markQueryResultRowsRaw(result: QueryResult): QueryResult {
|
||||
markRaw(result.rows);
|
||||
return result;
|
||||
|
|
@ -197,6 +201,12 @@ export const useQueryStore = defineStore("query", () => {
|
|||
}
|
||||
}
|
||||
|
||||
function clearResultRunSnapshots(tab: QueryTab) {
|
||||
for (const run of tab.resultRuns ?? []) {
|
||||
if (run.resultCacheKey) void deleteTabResultSnapshot(run.resultCacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
function projectResultRun(tab: QueryTab, run: NonNullable<QueryTab["resultRuns"]>[number]) {
|
||||
const activeIndex = run.activeResultIndex ?? 0;
|
||||
tab.activeResultRunId = run.id;
|
||||
|
|
@ -227,10 +237,33 @@ export const useQueryStore = defineStore("query", () => {
|
|||
touchResult(tab);
|
||||
}
|
||||
|
||||
function setActiveResultRun(id: string, runId: string) {
|
||||
async function restoreResultRunPayload(tab: QueryTab, runId: string) {
|
||||
const run = tab.resultRuns?.find((item) => item.id === runId);
|
||||
if (!run || run.result || run.results?.length) return run;
|
||||
|
||||
const cacheKey = run.resultCacheKey ?? tab.resultCacheKey;
|
||||
if (!cacheKey) return run;
|
||||
|
||||
const snapshot = await readTabResultSnapshot(cacheKey);
|
||||
const snapshotRun = snapshot?.resultRuns?.find((item) => item.id === runId);
|
||||
if (!snapshotRun) return run;
|
||||
|
||||
const restoredRun = {
|
||||
...run,
|
||||
...snapshotRun,
|
||||
result: snapshotRun.result ? markQueryResultRowsRaw(snapshotRun.result) : undefined,
|
||||
results: snapshotRun.results ? markQueryResultsRowsRaw(snapshotRun.results) : undefined,
|
||||
resultCacheState: "memory" as const,
|
||||
};
|
||||
tab.resultRuns = tab.resultRuns?.map((item) => (item.id === runId ? restoredRun : item));
|
||||
return restoredRun;
|
||||
}
|
||||
|
||||
async function setActiveResultRun(id: string, runId: string) {
|
||||
const tab = tabs.value.find((t) => t.id === id);
|
||||
const run = tab?.resultRuns?.find((item) => item.id === runId);
|
||||
if (!tab || !run) return false;
|
||||
if (!tab) return false;
|
||||
const run = await restoreResultRunPayload(tab, runId);
|
||||
if (!run?.result && !run?.results?.length) return false;
|
||||
projectResultRun(tab, run);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -240,6 +273,8 @@ export const useQueryStore = defineStore("query", () => {
|
|||
const runIndex = tab?.resultRuns?.findIndex((run) => run.id === runId) ?? -1;
|
||||
if (!tab || !tab.resultRuns || runIndex < 0) return false;
|
||||
|
||||
const removedRun = tab.resultRuns[runIndex];
|
||||
if (removedRun?.resultCacheKey) void deleteTabResultSnapshot(removedRun.resultCacheKey);
|
||||
const wasActive = tab.activeResultRunId === runId;
|
||||
const remainingRuns = tab.resultRuns.filter((run) => run.id !== runId);
|
||||
tab.resultRuns = remainingRuns;
|
||||
|
|
@ -261,6 +296,29 @@ export const useQueryStore = defineStore("query", () => {
|
|||
return (tab.resultRuns?.reduce((max, run) => Math.max(max, run.sequence), 0) ?? 0) + 1;
|
||||
}
|
||||
|
||||
function persistResultRun(tab: QueryTab, run: NonNullable<QueryTab["resultRuns"]>[number]) {
|
||||
const key = run.resultCacheKey ?? resultRunCacheKey(tab.id, run.id);
|
||||
run.resultCacheKey = key;
|
||||
run.resultCacheState = "memory";
|
||||
void writeTabResultSnapshot(key, {
|
||||
result: run.result,
|
||||
results: run.results,
|
||||
activeResultIndex: run.activeResultIndex,
|
||||
resultRuns: [run],
|
||||
activeResultRunId: run.id,
|
||||
queryAnalysis: run.queryAnalysis,
|
||||
querySourceColumns: run.querySourceColumns,
|
||||
queryEditabilityReason: run.queryEditabilityReason,
|
||||
tableMeta: run.tableMeta,
|
||||
resultPageSql: run.resultPageSql,
|
||||
resultPageLimit: run.resultPageLimit,
|
||||
resultPageOffset: run.resultPageOffset,
|
||||
resultCountSql: run.resultCountSql,
|
||||
resultTotalRowCount: run.resultTotalRowCount,
|
||||
cachedAt: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
function captureDisplayedResultRun(tab: QueryTab, sql: string, createdAt = Date.now()) {
|
||||
if (tab.mode !== "query" || !tab.result) return;
|
||||
const sequence = nextResultRunSequence(tab);
|
||||
|
|
@ -295,15 +353,26 @@ export const useQueryStore = defineStore("query", () => {
|
|||
queryEditabilityReason: tab.queryEditabilityReason,
|
||||
tableMeta: tab.tableMeta,
|
||||
};
|
||||
persistResultRun(tab, run);
|
||||
tab.resultRuns = [...(tab.resultRuns ?? []), run];
|
||||
tab.activeResultRunId = run.id;
|
||||
}
|
||||
|
||||
function toggleResultAutoSave(id: string): boolean {
|
||||
const tab = tabs.value.find((t) => t.id === id);
|
||||
if (!tab || tab.mode !== "query") return false;
|
||||
tab.resultAutoSave = tab.resultAutoSave ? undefined : true;
|
||||
if (tab.resultAutoSave && tab.result && !tab.activeResultRunId) {
|
||||
captureDisplayedResultRun(tab, tab.resultBaseSql ?? tab.lastExecutedSql ?? tab.sql);
|
||||
}
|
||||
return tab.resultAutoSave === true;
|
||||
}
|
||||
|
||||
function syncActiveResultRunFromDisplayed(tab: QueryTab) {
|
||||
if (!tab.activeResultRunId || !tab.resultRuns?.length) return;
|
||||
const index = tab.resultRuns.findIndex((run) => run.id === tab.activeResultRunId);
|
||||
if (index < 0) return;
|
||||
tab.resultRuns[index] = {
|
||||
const run = {
|
||||
...tab.resultRuns[index],
|
||||
result: tab.result,
|
||||
results: tab.results,
|
||||
|
|
@ -330,6 +399,17 @@ export const useQueryStore = defineStore("query", () => {
|
|||
queryEditabilityReason: tab.queryEditabilityReason,
|
||||
tableMeta: tab.tableMeta,
|
||||
};
|
||||
persistResultRun(tab, run);
|
||||
tab.resultRuns[index] = run;
|
||||
}
|
||||
|
||||
function syncDisplayedResultRun(tab: QueryTab, sql: string) {
|
||||
if (tab.mode !== "query" || !tab.result) return;
|
||||
if (tab.activeResultRunId) {
|
||||
syncActiveResultRunFromDisplayed(tab);
|
||||
} else if (tab.resultAutoSave) {
|
||||
captureDisplayedResultRun(tab, sql);
|
||||
}
|
||||
}
|
||||
|
||||
function resultRunHasPayload(run: NonNullable<QueryTab["resultRuns"]>[number]): boolean {
|
||||
|
|
@ -370,6 +450,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
whereInput: t.whereInput,
|
||||
pinned: t.pinned,
|
||||
mode: t.mode,
|
||||
resultAutoSave: t.resultAutoSave,
|
||||
structureTableName: t.structureTableName,
|
||||
objectBrowser: t.objectBrowser,
|
||||
objectSource: t.objectSource,
|
||||
|
|
@ -564,6 +645,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
if (tabs.value[idx].isExplaining) void cancelTabExplain(id);
|
||||
void closeResultSession(tabs.value[idx]);
|
||||
void closeClientConnectionSession(tabs.value[idx]);
|
||||
clearResultRunSnapshots(tabs.value[idx]);
|
||||
clearResultPayload(tabs.value[idx]);
|
||||
tabs.value.splice(idx, 1);
|
||||
if (activeTabId.value === id) {
|
||||
|
|
@ -600,6 +682,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
if (tab.isExplaining) void cancelTabExplain(tab.id);
|
||||
void closeResultSession(tab);
|
||||
void closeClientConnectionSession(tab);
|
||||
clearResultRunSnapshots(tab);
|
||||
clearResultPayload(tab);
|
||||
});
|
||||
const next = closeOtherTabsState(tabs.value, activeTabId.value, id);
|
||||
|
|
@ -614,6 +697,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
if (tab.isExplaining) void cancelTabExplain(tab.id);
|
||||
void closeResultSession(tab);
|
||||
void closeClientConnectionSession(tab);
|
||||
clearResultRunSnapshots(tab);
|
||||
clearResultPayload(tab);
|
||||
});
|
||||
const next = closeAllTabsState(tabs.value, activeTabId.value);
|
||||
|
|
@ -697,6 +781,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
if (tab.isExplaining) void cancelTabExplain(tab.id);
|
||||
void closeResultSession(tab);
|
||||
void closeClientConnectionSession(tab);
|
||||
clearResultRunSnapshots(tab);
|
||||
clearResultPayload(tab);
|
||||
});
|
||||
|
||||
|
|
@ -1150,6 +1235,10 @@ export const useQueryStore = defineStore("query", () => {
|
|||
}
|
||||
tab.executionId = executionId;
|
||||
tab.lastExecutedSql = sql;
|
||||
const updateActiveResultRun = !!tab.activeResultRunId && options?.preserveResultDuringExecution === true;
|
||||
if (!updateActiveResultRun) {
|
||||
tab.activeResultRunId = undefined;
|
||||
}
|
||||
if (!options?.preserveTotalRowCountDuringExecution) {
|
||||
tab.resultTotalRowCount = undefined;
|
||||
}
|
||||
|
|
@ -1236,7 +1325,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
current.tableMeta = undefined;
|
||||
current.resultBaseSql = options?.resultBaseSql ?? sql;
|
||||
current.resultSortedSql = options?.resultSortedSql;
|
||||
captureDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
syncDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
// Reflect db switches from SELECT N in the tab so the toolbar dropdown, tab title and
|
||||
// sidebar stay in sync with the command's effective db.
|
||||
if (current.database !== String(currentDb)) {
|
||||
|
|
@ -1294,7 +1383,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
current.tableMeta = undefined;
|
||||
current.resultBaseSql = options?.resultBaseSql ?? sql;
|
||||
current.resultSortedSql = options?.resultSortedSql;
|
||||
captureDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
syncDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -1320,7 +1409,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
current.tableMeta = undefined;
|
||||
current.resultBaseSql = options?.resultBaseSql ?? sql;
|
||||
current.resultSortedSql = options?.resultSortedSql;
|
||||
captureDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
syncDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -1352,7 +1441,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
current.tableMeta = undefined;
|
||||
current.resultBaseSql = options?.resultBaseSql ?? sql;
|
||||
current.resultSortedSql = options?.resultSortedSql;
|
||||
captureDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
syncDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -1379,7 +1468,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
current.tableMeta = undefined;
|
||||
current.resultBaseSql = options?.resultBaseSql ?? sql;
|
||||
current.resultSortedSql = options?.resultSortedSql;
|
||||
captureDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
syncDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -1420,7 +1509,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
current.tableMeta = undefined;
|
||||
current.resultBaseSql = options?.resultBaseSql ?? sql;
|
||||
current.resultSortedSql = options?.resultSortedSql;
|
||||
captureDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
syncDisplayedResultRun(current, options?.resultBaseSql ?? sql);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -1485,7 +1574,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
current.resultTotalRowCountLoading = false;
|
||||
}
|
||||
touchResult(current);
|
||||
captureDisplayedResultRun(current, queryBaseSql);
|
||||
syncDisplayedResultRun(current, queryBaseSql);
|
||||
if (current.mode === "query" && current.result) {
|
||||
countQueryTotalRowsInBackground({
|
||||
tabId: id,
|
||||
|
|
@ -1539,7 +1628,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
current.resultTotalRowCount = undefined;
|
||||
current.resultTotalRowCountLoading = false;
|
||||
touchResult(current);
|
||||
captureDisplayedResultRun(current, queryBaseSql);
|
||||
syncDisplayedResultRun(current, queryBaseSql);
|
||||
}
|
||||
} finally {
|
||||
const current = tabs.value.find((t) => t.id === id);
|
||||
|
|
@ -2006,6 +2095,7 @@ export const useQueryStore = defineStore("query", () => {
|
|||
setExecuting,
|
||||
setExecutingWithId,
|
||||
setErrorResult,
|
||||
toggleResultAutoSave,
|
||||
setActiveResultRun,
|
||||
removeResultRun,
|
||||
setActiveResultIndex,
|
||||
|
|
|
|||
|
|
@ -519,6 +519,7 @@ export interface QueryTab {
|
|||
activeResultIndex?: number;
|
||||
resultRuns?: QueryResultRun[];
|
||||
activeResultRunId?: string;
|
||||
resultAutoSave?: boolean;
|
||||
explainPlan?: import("@/lib/explainPlan").ParsedExplainPlan;
|
||||
explainError?: string;
|
||||
explainSql?: string;
|
||||
|
|
|
|||
Loading…
Reference in New Issue