diff --git a/apps/desktop/src/components/layout/ContentArea.vue b/apps/desktop/src/components/layout/ContentArea.vue
index d2de4b4eb2..97ad5d559f 100644
--- a/apps/desktop/src/components/layout/ContentArea.vue
+++ b/apps/desktop/src/components/layout/ContentArea.vue
@@ -210,7 +210,7 @@ import { loadQueryResultTransferSourceDdl } from "@/components/transfer/queryRes
import { formatDdlForDisplay } from "@/lib/sql/ddlDisplay";
import { sqlObjectNavigationTypeFromTableType } from "@/lib/sql/sqlNavigation";
import type { CustomSaveHandler } from "@/composables/useDataGridEditor";
-import type { QueryMessage, QueryResult, QueryTab, RedisResultViewMode, TableInfoTab, TreeNode, VectorCollectionMeta } from "@/types/database";
+import type { QueryMessage, QueryResult, QueryTab, RedisResultViewMode, TableInfoTab, TabOutputView, TreeNode, VectorCollectionMeta } from "@/types/database";
import type { SqlObjectNavigationTarget } from "@/lib/sql/sqlNavigation";
import { sqlFormatDialectForDbType, type SqlFormatDialect } from "@/lib/sql/sqlFormatter";
import { productionContextForDatabase } from "@/lib/database/productionSafety";
@@ -871,6 +871,14 @@ function setRedisResultViewMode(mode: RedisResultViewMode) {
queryStore.updateTabUiState(props.activeTab.id, { redisResultViewMode: mode });
}
+function selectOutputView(tabId: string, view: TabOutputView) {
+ queryStore.updateTabUiState(tabId, {
+ activeOutputView: view,
+ autoSwitchedToMessagesDuringExecution: false,
+ });
+ emit("update:activeOutputView", tabId, view);
+}
+
function observeStandaloneResultToolbar() {
standaloneResultToolbarResizeObserver?.disconnect();
standaloneResultToolbarResizeObserver = undefined;
@@ -1106,6 +1114,10 @@ watch(
() => props.activeTab.liveQueryMessages?.length ?? 0,
(count, previousCount) => {
if (count > 0 && !previousCount && props.activeTab.isExecuting && !props.editorOnly && !hasTabularResult.value && (props.activeOutputView === "result" || props.activeOutputView === "summary")) {
+ queryStore.updateTabUiState(props.activeTab.id, {
+ activeOutputView: "messages",
+ autoSwitchedToMessagesDuringExecution: true,
+ });
emit("update:activeOutputView", props.activeTab.id, "messages");
}
},
@@ -1126,6 +1138,7 @@ watch(
if (hasExecutionSummary.value && (!hasTabularResult.value || props.activeTab.result?.server_message === true) && props.activeOutputView === "result") {
const result = props.activeTab.result;
emit("update:activeOutputView", props.activeTab.id, result ? defaultViewForResult(result) : "summary");
+ return;
}
},
{ immediate: true },
@@ -2539,7 +2552,7 @@ defineExpose({
:result-mode="redisResultViewMode"
:message-count="resultMessageCount"
:compact="standaloneResultToolbarCompact"
- @select-view="emit('update:activeOutputView', activeTab.id, $event)"
+ @select-view="selectOutputView(activeTab.id, $event)"
@select-result-mode="setRedisResultViewMode"
/>
@@ -2809,7 +2822,7 @@ defineExpose({
:result-mode="redisResultViewMode"
:message-count="resultMessageCount"
:compact="compact"
- @select-view="emit('update:activeOutputView', activeTab.id, $event)"
+ @select-view="selectOutputView(activeTab.id, $event)"
@select-result-mode="setRedisResultViewMode"
/>
@@ -2831,7 +2844,7 @@ defineExpose({
class="inline-flex h-5 shrink-0 items-center gap-1 rounded-sm border border-transparent px-2 text-xs leading-none transition-colors"
:class="activeOutputView === 'profile' ? 'bg-secondary text-secondary-foreground' : 'text-muted-foreground hover:text-foreground'"
:aria-pressed="activeOutputView === 'profile'"
- @click="emit('update:activeOutputView', activeTab.id, activeOutputView === 'profile' ? 'result' : 'profile')"
+ @click="selectOutputView(activeTab.id, activeOutputView === 'profile' ? 'result' : 'profile')"
>
{{ t("profile.title") }}
@@ -2847,8 +2860,8 @@ defineExpose({
:archive-exporting="resultArchiveExporting"
:compact="compact"
:has-result="!!activeTab.result"
- @select-explain="emit('update:activeOutputView', activeTab.id, 'explain')"
- @select-profile="emit('update:activeOutputView', activeTab.id, 'profile')"
+ @select-explain="selectOutputView(activeTab.id, 'explain')"
+ @select-profile="selectOutputView(activeTab.id, 'profile')"
@export-archive="exportResultArchive"
@open-result-view="openPluginResultView"
/>
diff --git a/apps/desktop/src/components/layout/__tests__/ContentArea.serverMessages.spec.ts b/apps/desktop/src/components/layout/__tests__/ContentArea.serverMessages.spec.ts
index 1e06cdd069..8d9c4a0d0a 100644
--- a/apps/desktop/src/components/layout/__tests__/ContentArea.serverMessages.spec.ts
+++ b/apps/desktop/src/components/layout/__tests__/ContentArea.serverMessages.spec.ts
@@ -7,7 +7,7 @@ import type { QueryResult, QueryTab } from "@/types/database";
vi.mock("@/components/editor/QueryEditor.vue", () => ({ default: { render: () => null } }));
vi.mock("@/components/transfer/QueryResultTransferDialog.vue", () => ({ __esModule: true, default: { render: () => null } }));
-vi.mock("@/components/grid/DataGrid.vue", () => ({ default: { render: () => h("div", { "data-test": "data-grid" }) } }));
+vi.mock("@/components/grid/DataGrid.vue", () => ({ __esModule: true, default: { render: () => h("div", { "data-test": "data-grid" }) } }));
import ContentArea from "../ContentArea.vue";
import { useConnectionStore } from "@/stores/connectionStore";
@@ -95,4 +95,34 @@ describe("live server output", () => {
expect(host.textContent).toContain("running output");
expect(host.querySelector('[data-test="data-grid"]')).toBeNull();
});
+
+ it("marks autoSwitchedToMessagesDuringExecution in tab uiState when live messages arrive (#11822)", async () => {
+ const { state, tab } = await mountResults([], 0);
+ tab.isExecuting = true;
+ await nextTick();
+ tab.liveQueryMessages = [{ severity: "INFO", message: "function info message" }];
+ await nextTick();
+ expect(state.view).toBe("messages");
+ expect(useQueryStore().tabs.find((t) => t.id === tab.id)?.uiState?.autoSwitchedToMessagesDuringExecution).toBe(true);
+ });
+
+ it("clears autoSwitchedToMessagesDuringExecution when user explicitly selects an output view (#11822)", async () => {
+ const { host, state, tab } = await mountResults([], 0);
+ tab.isExecuting = true;
+ await nextTick();
+ tab.liveQueryMessages = [{ severity: "INFO", message: "function info message" }];
+ await nextTick();
+ expect(state.view).toBe("messages");
+ expect(useQueryStore().tabs.find((t) => t.id === tab.id)?.uiState?.autoSwitchedToMessagesDuringExecution).toBe(true);
+
+ tab.result = { columns: ["val"], rows: [[1]], affected_rows: 0, execution_time_ms: 1 };
+ tab.results = [tab.result];
+ await nextTick();
+
+ const buttons = host.querySelectorAll("[data-query-result-view-switcher] button");
+ buttons[0]?.click();
+ await nextTick();
+ expect(state.view).toBe("result");
+ expect(useQueryStore().tabs.find((t) => t.id === tab.id)?.uiState?.autoSwitchedToMessagesDuringExecution).toBe(false);
+ });
});
diff --git a/apps/desktop/src/composables/__tests__/useSqlExecution.spec.ts b/apps/desktop/src/composables/__tests__/useSqlExecution.spec.ts
index 1251943edc..bc57899646 100644
--- a/apps/desktop/src/composables/__tests__/useSqlExecution.spec.ts
+++ b/apps/desktop/src/composables/__tests__/useSqlExecution.spec.ts
@@ -778,7 +778,10 @@ SELECT @value AS Message;`;
// Mirrors the real order of events: the notice is surfaced live and the view moves to
// Messages, then the statement finishes with a tabular result.
activeOutputView.value = "messages";
- if (activeTab.value) activeTab.value.result = { columns: ["log_and_return"], rows: [["done"]], affected_rows: 0, execution_time_ms: 1, messages: [{ severity: "NOTICE", message: "working" }] };
+ if (activeTab.value) {
+ activeTab.value.uiState = { ...activeTab.value.uiState, autoSwitchedToMessagesDuringExecution: true };
+ activeTab.value.result = { columns: ["log_and_return"], rows: [["done"]], affected_rows: 0, execution_time_ms: 1, messages: [{ severity: "NOTICE", message: "working" }] };
+ }
});
vi.spyOn(useHistoryStore(), "add").mockResolvedValue(undefined);
@@ -793,6 +796,7 @@ SELECT @value AS Message;`;
expect(activeTab.value?.result?.rows).toEqual([["done"]]);
expect(activeOutputView.value).toBe("result");
+ expect(activeTab.value?.uiState?.autoSwitchedToMessagesDuringExecution).toBe(false);
});
it("keeps Messages selected when a completed run produced no tabular result", async () => {
@@ -853,6 +857,180 @@ SELECT @value AS Message;`;
expect(activeOutputView.value).toBe("messages");
});
+ it("redirects from messages to result when tabular data is produced after auto-switching (#11822)", async () => {
+ const sql = "SELECT * FROM test_func_with_info()";
+ const activeTab = ref({ ...queryTab("app"), sql });
+ const activeConnection = ref(connection("postgres"));
+ const activeOutputView = ref<"result" | "summary" | "explain" | "chart" | "messages">("result");
+ vi.spyOn(useQueryStore(), "executeCurrentSql").mockImplementation(async () => {
+ activeOutputView.value = "messages";
+ if (activeTab.value) {
+ activeTab.value.uiState = { ...activeTab.value.uiState, autoSwitchedToMessagesDuringExecution: true };
+ activeTab.value.result = {
+ columns: ["val"],
+ rows: [[1]],
+ affected_rows: 0,
+ execution_time_ms: 1,
+ messages: [{ severity: "INFO", message: "function info message" }],
+ };
+ }
+ });
+ vi.spyOn(useHistoryStore(), "add").mockResolvedValue(undefined);
+
+ const execution = useSqlExecution({
+ activeTab: computed(() => activeTab.value),
+ activeConnection: computed(() => activeConnection.value),
+ executableSql: computed(() => sql),
+ activeOutputView,
+ });
+
+ await execution.tryExecute();
+
+ expect(activeOutputView.value).toBe("result");
+ expect(activeTab.value?.uiState?.autoSwitchedToMessagesDuringExecution).toBe(false);
+ });
+
+ it("does not redirect from messages when query fails with error result (#11822)", async () => {
+ const sql = "SELECT * FROM test_func_with_error()";
+ const activeTab = ref({ ...queryTab("app"), sql });
+ const activeConnection = ref(connection("postgres"));
+ const activeOutputView = ref<"result" | "summary" | "explain" | "chart" | "messages">("result");
+ vi.spyOn(useQueryStore(), "executeCurrentSql").mockImplementation(async () => {
+ activeOutputView.value = "messages";
+ if (activeTab.value) {
+ activeTab.value.uiState = { ...activeTab.value.uiState, autoSwitchedToMessagesDuringExecution: true };
+ activeTab.value.result = {
+ columns: ["Error"],
+ execution_error: true,
+ rows: [["function exception"]],
+ affected_rows: 0,
+ execution_time_ms: 1,
+ messages: [{ severity: "INFO", message: "function info message" }],
+ };
+ }
+ });
+ vi.spyOn(useHistoryStore(), "add").mockResolvedValue(undefined);
+
+ const execution = useSqlExecution({
+ activeTab: computed(() => activeTab.value),
+ activeConnection: computed(() => activeConnection.value),
+ executableSql: computed(() => sql),
+ activeOutputView,
+ });
+
+ await execution.tryExecute();
+
+ expect(activeOutputView.value).toBe("messages");
+ expect(activeTab.value?.uiState?.autoSwitchedToMessagesDuringExecution).toBe(false);
+ });
+
+ it("does not redirect when user manually switched to messages mid-run (#11822)", async () => {
+ const sql = "SELECT * FROM test_func_with_info()";
+ const activeTab = ref({ ...queryTab("app"), sql });
+ const activeConnection = ref(connection("postgres"));
+ const activeOutputView = ref<"result" | "summary" | "explain" | "chart" | "messages">("result");
+ vi.spyOn(useQueryStore(), "executeCurrentSql").mockImplementation(async () => {
+ activeOutputView.value = "messages";
+ if (activeTab.value) {
+ // User manually selected messages mid-run, so autoSwitchedToMessagesDuringExecution is false
+ activeTab.value.uiState = { ...activeTab.value.uiState, autoSwitchedToMessagesDuringExecution: false };
+ activeTab.value.result = {
+ columns: ["val"],
+ rows: [[1]],
+ affected_rows: 0,
+ execution_time_ms: 1,
+ };
+ }
+ });
+ vi.spyOn(useHistoryStore(), "add").mockResolvedValue(undefined);
+
+ const execution = useSqlExecution({
+ activeTab: computed(() => activeTab.value),
+ activeConnection: computed(() => activeConnection.value),
+ executableSql: computed(() => sql),
+ activeOutputView,
+ });
+
+ await execution.tryExecute();
+
+ expect(activeOutputView.value).toBe("messages");
+ });
+
+ it("honors multiStatementDefaultView when redirecting multi-statement execution (#11822)", async () => {
+ const sql = "SELECT 1; SELECT 2;";
+ const activeTab = ref({ ...queryTab("app"), sql });
+ const activeConnection = ref(connection("postgres"));
+ const activeOutputView = ref<"result" | "summary" | "explain" | "chart" | "messages">("result");
+ const settingsStore = useSettingsStore();
+ settingsStore.editorSettings.multiStatementDefaultView = "summary";
+
+ vi.spyOn(useQueryStore(), "executeCurrentSql").mockImplementation(async () => {
+ activeOutputView.value = "messages";
+ if (activeTab.value) {
+ activeTab.value.uiState = { ...activeTab.value.uiState, autoSwitchedToMessagesDuringExecution: true };
+ activeTab.value.result = {
+ columns: ["val"],
+ rows: [[1]],
+ affected_rows: 0,
+ execution_time_ms: 1,
+ };
+ activeTab.value.results = [activeTab.value.result];
+ }
+ });
+ vi.spyOn(useHistoryStore(), "add").mockResolvedValue(undefined);
+
+ const execution = useSqlExecution({
+ activeTab: computed(() => activeTab.value),
+ activeConnection: computed(() => activeConnection.value),
+ executableSql: computed(() => sql),
+ activeOutputView,
+ });
+
+ await execution.tryExecute();
+
+ expect(activeOutputView.value).toBe("summary");
+ });
+
+ it("redirects background tab uiState to result when query finishes while tab is inactive (#11822)", async () => {
+ const sql = "SELECT * FROM test_func_with_info()";
+ const tab1: QueryTab = { ...queryTab("app"), id: "tab-1", sql, uiState: { activeOutputView: "messages", autoSwitchedToMessagesDuringExecution: true } };
+ const tab2: QueryTab = { ...queryTab("app"), id: "tab-2", sql: "SELECT 2", uiState: { activeOutputView: "chart" } };
+ const queryStore = useQueryStore();
+ queryStore.tabs = [tab1, tab2];
+ const activeTab = ref(tab2);
+ const activeConnection = ref(connection("postgres"));
+ const activeOutputView = ref<"result" | "summary" | "explain" | "chart" | "messages">("chart");
+
+ vi.spyOn(queryStore, "executeCurrentSql").mockImplementation(async (_sql, options) => {
+ const targetTab = queryStore.tabs.find((t) => t.id === options?.tabId);
+ if (targetTab) {
+ targetTab.uiState = { ...targetTab.uiState, activeOutputView: "messages", autoSwitchedToMessagesDuringExecution: true };
+ targetTab.result = {
+ columns: ["val"],
+ rows: [[1]],
+ affected_rows: 0,
+ execution_time_ms: 1,
+ };
+ }
+ });
+ vi.spyOn(useHistoryStore(), "add").mockResolvedValue(undefined);
+
+ const execution = useSqlExecution({
+ activeTab: computed(() => activeTab.value),
+ activeConnection: computed(() => activeConnection.value),
+ executableSql: computed(() => sql),
+ activeOutputView,
+ });
+
+ await execution.tryExecute(undefined, { tabId: tab1.id });
+
+ // Active tab (tab2) output view should remain untouched
+ expect(activeOutputView.value).toBe("chart");
+ // Background tab (tab1) uiState should have redirected to "result"
+ expect(tab1.uiState?.activeOutputView).toBe("result");
+ expect(tab1.uiState?.autoSwitchedToMessagesDuringExecution).toBe(false);
+ });
+
it("forwards execute-in-new-result-tab intent to the query store", async () => {
const sql = "SELECT * FROM users";
const activeTab = ref({ ...queryTab("app"), sql });
diff --git a/apps/desktop/src/composables/useSqlExecution.ts b/apps/desktop/src/composables/useSqlExecution.ts
index d378da4925..313083c08f 100644
--- a/apps/desktop/src/composables/useSqlExecution.ts
+++ b/apps/desktop/src/composables/useSqlExecution.ts
@@ -224,6 +224,13 @@ export function useSqlExecution(deps: {
return deps.activeTab.value?.id === tabId ? deps.activeTab.value : undefined;
}
+ function updateExecutionTabUiState(tab: QueryTab, patch: Partial>) {
+ queryStore.updateTabUiState(tab.id, patch);
+ if (!queryStore.tabs.some((candidate) => candidate.id === tab.id)) {
+ tab.uiState = { ...tab.uiState, ...patch };
+ }
+ }
+
function resolveExecutionConnection(tabId: string | undefined): ConnectionConfig | undefined {
const tab = resolveExecutionTab(tabId);
return (tab ? connectionStore.getConfig(tab.connectionId) : undefined) ?? deps.activeConnection.value;
@@ -480,6 +487,7 @@ export function useSqlExecution(deps: {
if (deps.activeTab.value?.id === executionTabId) {
deps.activeOutputView.value = redisConsoleSelected ? "result" : statementCount > 1 ? settingsStore.editorSettings.multiStatementDefaultView : "result";
}
+ updateExecutionTabUiState(tab, { autoSwitchedToMessagesDuringExecution: false });
const connName = executionConnection?.name || "";
const start = Date.now();
const isRedis = executionDatabaseType === "redis";
@@ -497,53 +505,62 @@ export function useSqlExecution(deps: {
cancelEditorViewportRequest(options.editorViewportRequestId);
return notStarted("busy", executionTabId);
}
+ const currentTab = resolveExecutionTab(executionTabId) ?? tab;
const executionTabStillActive = deps.activeTab.value?.id === executionTabId;
- const sqlServerMessageResultIndex = executionDatabaseType === "sqlserver" ? tab.results?.findIndex((result) => result.server_message === true) : undefined;
+ const sqlServerMessageResultIndex = executionDatabaseType === "sqlserver" ? currentTab.results?.findIndex((result) => result.server_message === true) : undefined;
if (sqlServerMessageResultIndex !== undefined && sqlServerMessageResultIndex >= 0) {
- focusSqlServerDataResult(tab.id, executionDatabaseType, tab);
+ focusSqlServerDataResult(currentTab.id, executionDatabaseType, currentTab);
if (executionTabStillActive) {
- deps.activeOutputView.value = tab.result?.server_message === true ? "messages" : "result";
+ deps.activeOutputView.value = currentTab.result?.server_message === true ? "messages" : "result";
}
- } else if (executionDatabaseType === "sqlserver" && tab.result?.server_message === true) {
+ } else if (executionDatabaseType === "sqlserver" && currentTab.result?.server_message === true) {
if (executionTabStillActive) {
deps.activeOutputView.value = "messages";
}
- } else if (tab.result && !tab.result.columns.length && !tab.results?.some((result) => result.columns.length > 0)) {
+ } else if (currentTab.result && !currentTab.result.columns.length && !currentTab.results?.some((result) => result.columns.length > 0)) {
if (executionTabStillActive && deps.activeOutputView.value !== "messages") {
- deps.activeOutputView.value = statementCount === 1 ? defaultViewForResult(tab.result) : "summary";
+ deps.activeOutputView.value = statementCount === 1 ? defaultViewForResult(currentTab.result) : "summary";
+ }
+ } else if (currentTab.uiState?.autoSwitchedToMessagesDuringExecution) {
+ const hasTabularData =
+ !firstQueryExecutionError(currentTab) &&
+ !!((currentTab.result?.columns.length && currentTab.result.server_message !== true && !isQueryExecutionErrorResult(currentTab.result)) || currentTab.results?.some((result) => result.columns.length > 0 && result.server_message !== true && !isQueryExecutionErrorResult(result)));
+ if (hasTabularData) {
+ const targetView = statementCount > 1 && settingsStore.editorSettings.multiStatementDefaultView === "summary" ? "summary" : "result";
+ updateExecutionTabUiState(currentTab, {
+ activeOutputView: targetView,
+ autoSwitchedToMessagesDuringExecution: false,
+ });
+ if (executionTabStillActive) {
+ deps.activeOutputView.value = targetView;
+ }
}
- } else if (executionTabStillActive && deps.activeOutputView.value === "messages" && ((tab.result?.columns.length ?? 0) > 0 || tab.results?.some((result) => result.columns.length > 0))) {
- // A notice can arrive before the statement produces its rows, so the live-output watcher
- // in ContentArea advances to Messages while it cannot yet know that data will follow.
- // Once the run finishes with a real result set, show the data again; Messages stays one
- // click away in the view switcher. Message-only runs and SQL Server PRINT batches are
- // handled by the branches above and keep their existing behavior.
- deps.activeOutputView.value = "result";
}
+ updateExecutionTabUiState(currentTab, { autoSwitchedToMessagesDuringExecution: false });
const elapsed = Date.now() - start;
- const failure = firstQueryExecutionError(tab);
+ const failure = firstQueryExecutionError(currentTab);
const success = !failure;
historyStore.add({
- connection_id: tab.connectionId,
+ connection_id: currentTab.connectionId,
connection_name: connName,
- database: tab.database,
+ database: currentTab.database,
sql,
execution_time_ms: elapsed,
success,
error: failure ? (failure.error ? translateBackendError(t, failure.error, failure.rows?.[0]?.[0]) : String(failure.rows?.[0]?.[0] ?? "")) : undefined,
activity_kind: classifySqlActivityKind(sql),
operation: primarySqlOperation(sql),
- affected_rows: success ? tab.result?.affected_rows : undefined,
+ affected_rows: success ? currentTab.result?.affected_rows : undefined,
});
if (success) {
- const refreshTarget = sqlMetadataRefreshTarget(sql, tab.schema);
+ const refreshTarget = sqlMetadataRefreshTarget(sql, currentTab.schema);
if (refreshTarget.scope === "connection") {
- connectionStore.invalidateMetadataCache(tab.connectionId);
- await invalidateObjectMetadataCache({ connectionId: tab.connectionId });
- await connectionStore.loadDatabases(tab.connectionId, { force: true });
+ connectionStore.invalidateMetadataCache(currentTab.connectionId);
+ await invalidateObjectMetadataCache({ connectionId: currentTab.connectionId });
+ await connectionStore.loadDatabases(currentTab.connectionId, { force: true });
} else if (refreshTarget.scope === "database") {
- await invalidateObjectMetadataCache({ connectionId: tab.connectionId, database: tab.database, schema: refreshTarget.schema });
- await connectionStore.refreshObjectListTreeNode(tab.connectionId, tab.database, refreshTarget.schema);
+ await invalidateObjectMetadataCache({ connectionId: currentTab.connectionId, database: currentTab.database, schema: refreshTarget.schema });
+ await connectionStore.refreshObjectListTreeNode(currentTab.connectionId, currentTab.database, refreshTarget.schema);
}
}
return {
diff --git a/apps/desktop/src/types/database.ts b/apps/desktop/src/types/database.ts
index 3ab9d793f6..11e5c2b4d5 100644
--- a/apps/desktop/src/types/database.ts
+++ b/apps/desktop/src/types/database.ts
@@ -2076,6 +2076,8 @@ export interface TabUiState {
/** Redis query results default to grid; a per-tab override selects command-line output. */
redisResultViewMode?: RedisResultViewMode;
resultPaneOpen?: boolean;
+ /** Tracks whether the active output view was auto-switched to "messages" by live server output during execution. */
+ autoSwitchedToMessagesDuringExecution?: boolean;
/** Small JSON-compatible snapshots owned by special-page components. */
page?: Record;
}