Skip to content

fix(database): add sort columns to select to avoid DISTINCT subquery error#2564

Open
suvvvv wants to merge 2 commits into
OneUptime:masterfrom
suvvvv:fix/sort-column-not-in-select-distinct-error
Open

fix(database): add sort columns to select to avoid DISTINCT subquery error#2564
suvvvv wants to merge 2 commits into
OneUptime:masterfrom
suvvvv:fix/sort-column-not-in-select-distinct-error

Conversation

@suvvvv

@suvvvv suvvvv commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

What

Fixes a 500 error when querying a model by a sort column that was not explicitly listed in select, on models that load relations.

GET /api/incident-state-timeline/get-list (or alert-state-timeline) with sort: {"startsAt": "ASC"} currently fails with:

QueryFailedError: column "distinctAlias.AlertStateTimeline_startsAt" does not exist

Root cause

These models load relations (via @CanAccessIfCanReadOn), so TypeORM paginates with a DISTINCT subquery and references the sort columns in the outer ORDER BY:

SELECT DISTINCT "distinctAlias"."AlertStateTimeline__id",
                "distinctAlias"."AlertStateTimeline_startsAt"
FROM ( SELECT "AlertStateTimeline"."_id", "AlertStateTimeline"."alertStateId" ... ) "distinctAlias"
ORDER BY "distinctAlias"."AlertStateTimeline_startsAt" ASC

startsAt is in the outer ORDER BY but not in the inner SELECT, so Postgres cannot resolve it.

Fix

In DatabaseService._findBy, ensure every scalar sort column is present in the select map before calling repository.find(), and strip the auto-added columns from the returned items so callers only get back what they requested.

  • Generalizes the existing createdAt-only handling — the default createdAt sort now flows through the same path.
  • Skips nested/relation sorts.
  • No change to the API contract: auto-added columns are removed from results.
- let automaticallyAddedCreatedAtInSelect: boolean = false;
+ const automaticallyAddedSortKeysInSelect: Array<string> = [];
  ...
- if (!(findBy.select as any)["createdAt"]) {
-   (findBy.select as any)["createdAt"] = true;
-   automaticallyAddedCreatedAtInSelect = true;
- }
+ for (const sortKey of Object.keys(findBy.sort)) {
+   if (typeof (findBy.sort as any)[sortKey] === Typeof.Object) { continue; }
+   if (!(findBy.select as any)[sortKey]) {
+     (findBy.select as any)[sortKey] = true;
+     automaticallyAddedSortKeysInSelect.push(sortKey);
+   }
+ }

Tests

New Common/Tests/Server/Services/DatabaseService.test.ts with 4 cases:

  1. A sorted-but-unselected column is added to the select passed to the repository.
  2. That auto-added column is stripped from returned items.
  3. A sort column the caller explicitly selected is preserved.
  4. The default createdAt sort is applied and stripped (no regression).

The two bug-specific tests fail without the source change, confirming they are real regression guards.

node node_modules/.bin/jest --runInBand ./Tests/Server/Services/DatabaseService.test.ts
# 4 passed

Prettier-clean and type-checks pass.

Fixes #2476

…error

Sorting a query by a column that was not in the select crashed with
`column "distinctAlias.<Model>_<col>" does not exist` on models that load
relations (e.g. timeline models via @CanAccessIfCanReadOn). TypeORM
paginates such queries with a DISTINCT subquery and references the sort
columns in the outer ORDER BY; if a sort column is not selected, it is
absent from the inner subquery and Postgres cannot resolve it.

_findBy now adds every scalar sort column to the select (generalizing the
previous createdAt-only handling) and strips the auto-added columns from
the returned items so callers still get back only what they requested.
Nested/relation sorts are skipped.

Adds regression tests covering: the sort column being selected, the
auto-added column being stripped, an explicitly selected sort column being
preserved, and the default createdAt sort still working.

Fixes OneUptime#2476

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@simlarsen

simlarsen commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

Sorting by non-selected column crashes with DISTINCT subquery error on timeline models

2 participants