Skip to content

fix(db): closing a table tab force-closes the read-only session other views are using #1215

Description

@ZhuchkaTriplesix

Part of #1212.

Problem

Closing a table browser tab force-closes the read-only session that other views are using.

  • GenericTableView.dispose() calls widget.delegate.cancel(interruptIfBusy: true) (lib/features/workspace/generic_table_view.dart:289).
  • Despite the name, the delegates never check whether anything is running. They interrupt the readOnly and the tableWrite slot of the connection and database unconditionally:
    • PostgreSQL: PostgresTableDataDelegate.cancel (lib/features/postgresql/postgres_table_view.dart:238)
    • MySQL: lib/features/mysql/mysql_table_view.dart:237
    • SQLite: lib/features/sqlite/sqlite_table_view.dart:225
  • interrupt removes the pool entry and calls forceClose() on its connection. That connection is the same object every readOnly caller of this database holds: the tree catalog, stats dashboards, other open table tabs, the Relations view and MCP calls.

Effects:

Scope

  • dispose() releases the lease and never closes a shared session.
  • Track in-flight calls per delegate. Only when this delegate has a statement running, cancel that statement:
    • PostgreSQL: a cancel request for the backend (Connection.cancelPendingStatement() in postgres 3.x) — the socket stays open.
    • MySQL: KILL QUERY <connection id> from a separate short-lived connection, or release the lease and let the statement finish.
    • SQLite: release only (statements are local).
  • Rename interruptIfBusy or make it do what it says.
  • Check the other callers of interrupt / interruptAllModes for the same pattern (workspace close, connection switch) and keep force-close only where the whole connection is meant to go away (disconnect, delete).

Acceptance

  • Widget test: two table tabs on the same database; close one while the other loads a page (fake delegate that blocks) → the other one finishes without reconnecting.
  • Unit test: dispose of an idle table delegate does not call interrupt / forceClose.
  • Unit test: dispose while its own statement runs sends a cancel for that statement and leaves the shared connection connected.

Activity

  1. added
    bugSomething isn't working
    stabilityTheme parser epic label: stability
    coreCore library logic and services
    connectionsDatabase connections, URI parsing, pools
    P1High priority / Core capability
    on Oct 9, 2026
  2. added 2 commits that reference this issue on Oct 9, 2026
  3. ZhuchkaTriplesix commented on Oct 9, 2026

    @ZhuchkaTriplesix
    MemberAuthor

    Closed by #1221 and #1236.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High priority / Core capabilitybugSomething isn't workingconnectionsDatabase connections, URI parsing, poolscoreCore library logic and servicesstabilityTheme parser epic label: stability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions