Skip to content

fix(datagrid): apply default row sort on the first table load (#1603)#1604

Merged
datlechin merged 3 commits into
mainfrom
fix/default-row-sort-1603
Jun 6, 2026
Merged

fix(datagrid): apply default row sort on the first table load (#1603)#1604
datlechin merged 3 commits into
mainfrom
fix/default-row-sort-1603

Conversation

@datlechin
Copy link
Copy Markdown
Member

Fixes #1603.

Problem

Setting Default row sort to Primary key stopped sorting PostgreSQL tables (regression in v0.49.0). Even when it did work, the rows loaded unsorted first and then re-sorted, instead of arriving sorted like TablePlus.

Root cause

v0.49.0 (#1582) split table loading into two phases: render rows first, fetch metadata second. For PostgreSQL the primary key only arrives in phase 2, but the default-sort step ran in phase 1 with no primary key, produced an empty sort, and permanently set the "already evaluated" flag, so the real primary key from phase 2 was never used. MySQL and MariaDB escaped this because their wire protocol carries primary-key flags inline in every result, so phase 1 already knew the key.

Fix

Resolve the default sort before the first table query, from the table's schema, so a single query comes back already sorted. The None default keeps the fast unsorted render from #1582 untouched; only tables opened with a Primary key or First column default sort wait for a quick primary-key lookup, which is what produces the sorted-from-the-start result.

  • New MainContentCoordinator+DefaultSort.swift: gate + resolver that loads schema columns/keys, sets the sort state, rebuilds the query, then runs one sorted query.
  • executeTableTabQueryDirectly() detours through the resolver when a non-none default sort is pending.
  • rebuildTableQuery falls back to cached schema columns when no rows are loaded yet, so ORDER BY resolves before the first fetch.
  • Removed the old post-load re-query path (the source of the unsorted flash and the duplicate query).

Reuses the existing schemaColumnsCache / loadSchemaColumns that the column-scoping path already relies on, so this is not a new fetch pattern.

Tests

DefaultSortInitialQueryTests.swift covers the schema-column ORDER BY fallback (the exact thing that was missing for PostgreSQL) and the gate logic. swiftlint lint --strict passes clean.

A UI test isn't included because the flow needs a live PostgreSQL connection, which is not deterministic in CI.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89b79066c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

filterCoordinator.rebuildTableQuery(at: index)
}

runQuery()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Re-check the target tab before running the query

Because loadSchemaColumns awaits metadata before this call, the selected tab can change (or the preview tab can be reused for another table while preserving the same tab id) before the resolver resumes. This unconditional runQuery() executes whatever tab is currently selected rather than the tabId being resolved, and in the reused-tab case can apply the stale resolver to the new table; the previous post-load path guarded selectedTabId == tabId before re-querying. Please re-check that the target tab is still selected and still represents the same table/schema before rebuilding/executing.

Useful? React with 👍 / 👎.

datlechin added 2 commits June 6, 2026 19:20
Signed-off-by: Ngô Quốc Đạt <datlechin@gmail.com>
@datlechin datlechin merged commit 7077abd into main Jun 6, 2026
4 checks passed
@datlechin datlechin deleted the fix/default-row-sort-1603 branch June 6, 2026 12:21
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f48086df21

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

defaultSortResolveTask?.cancel()
if shouldResolveDefaultSort(for: tab) {
let tabId = tab.id
tabManager.mutate(at: index) { $0.execution.didEvaluateDefaultSort = true }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Defer marking default sort evaluated until resolver completes

If the user triggers another table execution/refresh while loadSchemaColumns is still in flight, the next executeTableTabQueryDirectly() cancels defaultSortResolveTask at line 858, but this flag has already been set, so shouldResolveDefaultSort returns false and the tab runs its original unsorted query; because the flag remains true, the default sort is never retried for that table load. Consider setting this only after the resolver finishes or clearing it when the resolve task is canceled.

Useful? React with 👍 / 👎.

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.

Default row sort broken

1 participant