From 8642355c17055233d2f8baaa5dc86fa0906ce53b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 11 Nov 2026 00:33:31 +0000 Subject: [PATCH] fix: drop stale profile when a tab moves to SQLite A tab taken over by a newly opened SQLite file, or moved to one from the schema tree, kept the profile of the server it was on, so the next start reconnected that server and bound the tab back to it. Closes #962 Co-Authored-By: Claude Fable 5.2 Claude-Session: https://claude.ai/code/session_014tzYxya6Umczq4EBPTYkX4 --- .../__tests__/useConnectionSwitching.test.ts | 25 +++++++++++++++++++ .../layout/useConnectionSwitching.ts | 5 +++- src/components/schema/SchemaTree.tsx | 4 ++- src/stores/editorStore.ts | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/layout/__tests__/useConnectionSwitching.test.ts b/src/components/layout/__tests__/useConnectionSwitching.test.ts index 99381478..4baecf89 100644 --- a/src/components/layout/__tests__/useConnectionSwitching.test.ts +++ b/src/components/layout/__tests__/useConnectionSwitching.test.ts @@ -110,4 +110,29 @@ describe("editor tab and selected connection agree (#788)", () => { expect(activeTab()?.connectionId).toBe("sqlite-1"); expect(useEditorStore.getState().tabs.find((t) => t.id === "tab-0")?.connectionId).toBe("dev"); }); + + it("drops the old server's profile from a tab a SQLite file takes over (#962)", () => { + // The tab's server is gone, so the file takes the tab rather than a new one. + setConnections([], null); + const { result } = renderHook(() => useConnectionSwitching()); + useSqliteStore.setState({ sessions: [{ id: "sqlite-1", path: "data.db" } as unknown as SqliteSession] }); + + act(() => result.current.attachSqliteSession("sqlite-1")); + + expect(activeTab()?.id).toBe("tab-0"); + expect(activeTab()?.connectionId).toBe("sqlite-1"); + // Kept, it would reconnect p-dev and bind the tab back to it at the next start. + expect(activeTab()?.profileId).toBeUndefined(); + }); + + it("replaces the old server's profile on a tab a new server takes over", () => { + setConnections([], null); + const { result } = renderHook(() => useConnectionSwitching()); + setConnections([prod], "prod"); + + act(() => result.current.attachNewConnection(prod)); + + expect(activeTab()?.id).toBe("tab-0"); + expect(activeTab()?.profileId).toBe("p-prod"); + }); }); diff --git a/src/components/layout/useConnectionSwitching.ts b/src/components/layout/useConnectionSwitching.ts index 9ea8235f..7e8e9942 100644 --- a/src/components/layout/useConnectionSwitching.ts +++ b/src/components/layout/useConnectionSwitching.ts @@ -75,7 +75,10 @@ export function useConnectionSwitching() { if (active && !activeHasServer) { // Only a tab with no live server is taken over, so this does not // normally move a session; through the guard all the same (#843). - requestTabConnection(active.id, connectionId, conn?.database ?? undefined, conn?.profile_id); + // A SQLite file has no profile. `null` drops the one the tab still has + // from the server it was on, which would otherwise send it back there + // at the next start (#962). + requestTabConnection(active.id, connectionId, conn?.database ?? undefined, conn?.profile_id ?? null); return; } openTabFor(connectionId, conn); diff --git a/src/components/schema/SchemaTree.tsx b/src/components/schema/SchemaTree.tsx index bfec03ab..3708c593 100644 --- a/src/components/schema/SchemaTree.tsx +++ b/src/components/schema/SchemaTree.tsx @@ -129,7 +129,9 @@ export function SchemaTree({ connectionId }: { connectionId: string }) { const selectDatabase = (dbName: string) => { if (!activeTabId) return; const conn = activeConnections.find((c) => c.id === connectionId); - requestTabConnection(activeTabId, connectionId, dbName, conn?.profile_id); + // `null` for a tree with no profile (a SQLite file), so the tab does not + // keep the profile of the server it is moved from (#962). + requestTabConnection(activeTabId, connectionId, dbName, conn?.profile_id ?? null); }; // Tracks pending single-click timers keyed by "db.name" diff --git a/src/stores/editorStore.ts b/src/stores/editorStore.ts index a0932c73..a1f99d6a 100644 --- a/src/stores/editorStore.ts +++ b/src/stores/editorStore.ts @@ -155,7 +155,7 @@ interface EditorState { * server where its transaction is open (#843). `setTabConnection` sets it * unconditionally. */ - requestTabConnection: (id: string, connectionId: string, database?: string, profileId?: string) => void; + requestTabConnection: (id: string, connectionId: string, database?: string, profileId?: string | null) => void; setActiveTab: (id: string) => void; updateTabContent: (id: string, content: string) => void; /**