Skip to content

fix(editor): close the query tab review findings - #2895

Merged
datlechin merged 1 commit into
mainfrom
fix/query-tab-review-findings
Sep 15, 2026
Merged

datlechin merged 1 commit into
mainfrom
fix/query-tab-review-findings

Conversation

@datlechin

Copy link
Copy Markdown
Member

Follow-up to #2892. A second model reviewed that branch after it merged and found ten defects in it;
this closes all ten. Nothing here is new behaviour, it is the rewrite finished correctly.

Correctness

A pinned failure read as a success. resolveSettledResult tested only execution.errorMessage,
which the tab clears on the next run, while the pinned ResultSet keeps its own. Pin a failed
query, run something that works, switch back, and the result reported no columns and no error, so it
resolved to the "statement succeeded" view over a query that had failed. QueryResultInputs now
carries activeResultErrorMessage, and one resolvedError helper answers for the banner and for the
success gate together.

The find bar outlived the grid it searches. showsFindBar tested the tab type and not the view
mode, so switching a table tab from Data to JSON, Chart, Map or Structure left the find bar mounted
over an unmounted data-grid coordinator. ResultsViewMode.showsFindBar already existed and is now
part of the condition. The old code got this right by accident, because the find bar was built
inside the .data arm of the switch this PR's parent flattened.

Clear Results was unreachable at the moment it was wanted. Clear Query deliberately leaves the
results standing, and it takes canRun away with it. Because Run was a Menu(primaryAction:)
disabled on canRun, the whole menu went with it, including the Clear Results entry inside it. Run
is now a real split button: a ControlGroup whose Button and Menu are separately enabled, with
canOpenRunMenu covering "anything in here is live". The same bug hid both clears whenever the
connection was unavailable.

The two new Query menu commands were always enabled. MainSplitViewController.isEnabled had no
arm for clearQuery(_:) or clearResults(_:), so they fell through to true and did nothing when
clicked on a table tab, an empty editor, or a window with no command actions.
MenuValidationContext gains canClearQuery and canClearResults.

Clear Query left the dirty dot stale. The editor's text binding recomputes
window.isDocumentEdited on every keystroke; a command that empties the tab without going through
that binding did not. A scratch tab kept a dot it no longer deserved and a cleared file-backed tab
was not marked modified. Both now call MainContentCoordinator.refreshUnsavedIndicator(), which is
the binding's own logic given a name.

Trailing pane

History was replaced by a row click. revealInspectorForSelection guarded only
isAssistantVisible, so with Auto-show inspector on, clicking any grid row closed a deliberately
opened History pane and persisted Inspector as that connection's surface. The guard now covers both.

History could mount deactivated. HistoryPanelView keys its activation on
HistoryPanelState.isVisible, and the synchroniser ran only from explicit reveal and hide. A
workspace switch onto a connection whose remembered surface was .history, or a divider drag that
collapsed the pane, left the flag disagreeing with the pane: a mounted, permanently blank History.
syncHistoryPanelVisibility() now runs from showSelectedTrailingPane(), which every reveal, hide,
workspace switch and availability change already ends in, and from splitViewDidResizeSubviews.

An upgrading user lost their open history. #2892 moved the drawer into the trailing pane without
carrying the persisted state across, so anyone whose drawer was open at shutdown got Inspector
instead. TrailingPaneState adopts .history when no surface has ever been stored for the
connection and the history preferences say it was visible. Deterministic and one-time without a
migration flag: the branch is reachable only while no surface is stored, and storing one is what
changing it does.

Layout and onboarding

A long result name set the bar's width. compactTitle returned the full label for a single
result, and the chooser is fixedSize inside every ViewThatFits tier, so a result named after a
long identifier could push the grid out of a 400pt pane. Bounded to 16 characters; the full name
stays on the menu entry and the accessibility label.

The Find Past Queries tip had no anchor. The rewrite dropped the FeatureTipPopoverAnchor, and
nothing else instantiates FindPastQueriesTip, so its donated rule could never present. Reattached
to the Run menu, which is the control that produces the history the tip points at.

Verification

  • verify.sh build: PASS
  • verify.sh test QueryResultPresentationTests QueryCommandAvailabilityTests ResultSetMenuModelTests ResultSetPolicyTests: PASS, 41 executed, 41 passed
  • verify.sh lint TablePro: PASS, 0 violations

Two regression tests added for the two findings that are pure logic: pinnedFailureStaysAFailure
and findBarFollowsMode in QueryResultPresentationTests, and runMenuOutlivesRun in
QueryCommandAvailabilityTests. The trailing-pane and dirty-indicator fixes are AppKit window state
and are covered by the existing UI suites rather than by new unit tests.

No CHANGELOG entry: #2892 is still unreleased, and per the repo's rules a fix to something unreleased
folds into the original entry rather than adding a "Fixed" line. The entries #2892 added already
describe the behaviour this PR makes true.

@datlechin
datlechin merged commit 7fb1919 into main Sep 15, 2026
8 of 12 checks passed
@datlechin
datlechin deleted the fix/query-tab-review-findings branch September 15, 2026 11:21
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