Skip to content

fix(databases): pin the grid sort tie breaker to the sort direction - #3153

Closed
HarshMN2345 wants to merge 4 commits into
mainfrom
fix/grid-sort-tie-breaker-direction
Closed

fix(databases): pin the grid sort tie breaker to the sort direction#3153
HarshMN2345 wants to merge 4 commits into
mainfrom
fix/grid-sort-tie-breaker-direction

Conversation

@HarshMN2345

Copy link
Copy Markdown
Member

What does this PR do?

Descending sorts in the database grid were forcing a full filesort on the server.

The API appends $sequence as a tie breaker to any sort that has no unique attribute (Database::find), but it appends it without an order type, so the SQL adapter defaults it to ASC. A grid sort of orderDesc(column) therefore reached the engine as:

ORDER BY `column` DESC, `_id` ASC

That direction mix matches neither scan direction of the index, so MySQL/MariaDB falls back to sorting the whole table. On large tables a 50-row page took seconds, and at times hit the 15s query timeout and returned a 408.

This sends $sequence explicitly, in the same direction as the sort, so the index stays usable:

ORDER BY `column` DESC, `_id` DESC

Ascending sorts already lined up with the appended tie breaker and are left untouched, as are sorts already on $id or $sequence. The default (unsorted) grid query is unchanged — Query.orderDesc('') already resolves to plain _id DESC.

Three call sites, covering tables and collections:

  • buildGridQueries() in database-[database]/store.ts — the page-load path, where the user's sort comes back off the URL query param
  • getCorrectOrderQueries() in table-[table]/spreadsheet.svelte and collection-[collection]/spreadsheet.svelte — the client-side pagination path

Test Plan

Open a table with enough rows for the index to matter, sort a column descending, and page through it. The outbound request now carries a trailing {"method":"orderDesc","attribute":"$sequence"}, and the resulting ORDER BY is single-direction. Ascending sorts and the unsorted default produce the same queries as before.

Ran bun run format && bun run check && bun run lint && bun run test:unit && bun run build — 0 errors, 239 unit tests passing, build clean.

Related PRs and Issues

Worth noting that this only covers the console. The same mixed-direction ORDER BY affects any SDK caller that sorts descending on a non-unique attribute, which is where the slow /v1/users and /v1/storage/.../files queries are coming from. The general fix is for the appended tie breaker to inherit the direction of the preceding order attribute in utopia-php/database.

The API appends `$sequence` to any sort that has no unique attribute, and
always ascending. A descending grid sort therefore reached the engine as
`column DESC, _id ASC` — a direction mix neither scan direction of the index
can serve, so it filesorted the whole table. On large tables that turned a
25-row page into seconds of work, up to a query timeout.

Send `$sequence` ourselves, in the same direction as the sort, so the index
stays usable. Ascending sorts already lined up with the appended tie breaker
and are left alone, as are sorts already on `$id` or `$sequence`.
@greptile-apps

greptile-apps Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR fixes descending database-grid sorts by appending an explicit descending $sequence tie breaker while preserving existing ascending and default ordering behavior.

  • Detects sort queries by their parsed method instead of matching substrings in filter values.
  • Applies the tie breaker consistently to initial and client-side pagination for tables and collections.
  • Updates nanoid and postcss patch versions and refreshes the Bun lockfile.

Confidence Score: 5/5

The PR appears safe to merge.

The prior filter-versus-sort defect is fixed by checking the parsed query method, and no blocking failure remains.

Important Files Changed

Filename Overview
src/routes/(console)/project-[region]-[project]/databases/database-[database]/store.ts Replaces substring-based sort detection with method-aware parsing and appends $sequence DESC only for descending non-unique sorts; the previously reported filter misclassification is fixed.
src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/spreadsheet.svelte Uses shared order detection and tie-breaker helpers across table sorting and pagination paths.
src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/spreadsheet.svelte Mirrors the corrected order handling across collection sorting and pagination paths.
package.json Updates the nanoid and postcss patch-version ranges with matching lockfile resolutions.
bun.lock Refreshes direct and transitive resolutions for the nanoid and postcss updates.

Reviews (3): Last reviewed commit: "chore(deps): raise the nanoid floor to c..." | Re-trigger Greptile

`orderAsc`/`orderDesc` can appear inside a filter's value, so searching the
serialized query for that text can pick a filter instead of the sort. When a
filter like that was added before a descending sort, the tie breaker was
skipped and the sort fell back to the mixed-direction filesort.

Parse the query and compare its method. Applies to the same substring check in
`extractSortFromQueries` and in the grid's `sort()`, where a matching filter
would have been silently dropped when the user changed the sort.
GHSA-28wg-ghj8-5hjv and GHSA-2v37-7h3g-55p8 patch the 3.x line at 3.3.17 and
the 5.x line at 5.1.16, so no single override covers both: forcing 5.x onto
postcss would hand a CJS consumer an ESM-only package.

Every consumer's declared range already permits a patched release, so only the
pinned floors and the resolved versions move:

  nanoid (direct)          ^5.1.11 -> ^5.1.16
  postcss (override)       ^8.5.18 -> ^8.5.26, which floors nanoid at ^3.3.17
  @ai-sdk/provider-utils    3.3.11 ->  3.3.18  (declares ^3.3.8)
  @melt-ui/svelte            5.1.7 ->  5.1.16  (declares ^5.0.4)
  postcss                   3.3.16 ->  3.3.18  (declares ^3.3.17)

Integrity hashes come from the registry and no other package is touched.
`bun install --frozen-lockfile` leaves the lockfile byte-identical.
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