Skip to content

fix(datagrid): keep staged structure and table-draft edits across a tab switch - #2239

Merged
datlechin merged 1 commit into
mainfrom
fix/structure-edits-survive-tab-switch
Aug 19, 2026
Merged

fix(datagrid): keep staged structure and table-draft edits across a tab switch#2239
datlechin merged 1 commit into
mainfrom
fix/structure-edits-survive-tab-switch

Conversation

@datlechin

Copy link
Copy Markdown
Member

Stacked on #2238. Review that one first; this PR's base is its branch.

Found while investigating #2238. Staged structure changes and an in-progress table definition were destroyed by an ordinary tab switch, with no prompt and nothing in Undo. No close-path gate can catch this, which is why it could not ship with #2238.

Root cause

MainEditorContentView builds only the selected tab's content (MainEditorContentView.swift:101), and the results view mode is a switch inside that. Both are _ConditionalContent branches, so switching tabs, and switching a table tab between Data and Structure, tear the view down and take its @State with it. TableStructureView held structureChangeManager there, and CreateTableView held the whole definition there.

The reload made it worse rather than better. StructureChangeManager.loadSchema is what adopts a new baseline, and it clears every pending change, the validation errors and the undo stack (StructureChangeManager.swift:95-98). So a rebuild that refetched the schema would have discarded the edits on the way back in even if the manager had survived.

The fix

The same shape the file already uses for the Users & Roles, ER diagram, dashboard and Query Insights view models: per-tab state cached outside the view.

  • StructureEditingSession holds the change manager plus the loaded baseline it is staged against. The baseline travels with it deliberately: holding it is what lets a rebuild skip the fetch, and skipping the fetch is the only version of this that keeps the edits. loadInitialData now runs once per session rather than once per view.
  • CreateTableDraft holds the table name, the options and the change manager. A Create Table tab is unsaved by definition, since nothing exists on the server until Create is pressed.
  • Both live on MainContentCoordinator next to the existing per-tab displayFormatsCache, and are pruned by the same cleanupTabCaches. That placement is load-bearing rather than tidiness: the close gate from fix(tabs): ask before closing a tab that holds unsaved work #2238 has to see the staged work of a tab the user is not looking at, and view @State is invisible to it.
  • The unsaved-work predicate reads them, so closing a tab, closing the window or quitting now asks about staged structure edits and unfinished table definitions instead of discarding them.
  • CreateTableDraft.holdsWork deliberately ignores the blank column the editor seeds so the grid has a row. Counting it would prompt on every empty Create Table tab the user closes.

A genuine refresh still refetches, through onRefreshData, which already asks before discarding.

TableStructureView's moved properties became forwarding computed properties with nonmutating set, so all ~105 references across the view and its two extensions are unchanged. Nothing took a binding projection on them, which is what made that safe.

Verification

  • verify.sh build: PASS
  • verify.sh test TabCloseProtectionTests CommandActionsBulkCloseTests QueryTabProtectionTests ConnectionCloseActionTests MainContentCoordinatorTabSwitchTests: PASS, 70 executed, 70 passed, 0 failed
  • swiftlint --strict over every changed file: clean

Six new cases cover a background table tab reporting its staged ALTERs, a session keeping them across a rebuild, an untouched Create Table draft staying unprompted, a named one being gated, and a closed tab dropping both.

No TableProUITests automation: driving this needs a live connection with a real table to open the Structure tab against, which the suite has no fixture for.

Before / After

No screenshot: the change is that state stops disappearing. The visible difference is a Structure tab that still shows a pending column after you visit another tab, where it previously showed none.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Base automatically changed from fix/warn-before-closing-tab-with-unsaved-work to main August 19, 2026 11:40
@datlechin
datlechin force-pushed the fix/structure-edits-survive-tab-switch branch from 3d551b4 to e41dffa Compare August 19, 2026 11:40
@mintlify

mintlify Bot commented Aug 19, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🔴 Failed Aug 19, 2026, 11:41 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@datlechin
datlechin merged commit e5c30e9 into main Aug 19, 2026
2 checks passed
@datlechin
datlechin deleted the fix/structure-edits-survive-tab-switch branch August 19, 2026 11:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant