Skip to content

Conversation

samwillis
Copy link
Collaborator

fixes #610

Description of the fix from Claude:

Fix: orderBy breaks when collection alias matches schema field name

Problem

When a collection alias in the from clause had the same name as one of its schema fields, orderBy would fail to sort correctly. For example:

type EmailSchema = {
  email: string
  createdAt: Date
}

// This would break - alias "email" conflicts with the "email" field
q.from({ email: emailCollection })
 .orderBy(({ email }) => email.createdAt, "desc")

The query would run but produce unsorted results.

Root Cause

The orderBy compiler was constructing an evaluation context by spreading the row data and then __select_results:

const orderByContext = { ...row }
if (row.__select_results) {
  Object.assign(orderByContext, row.__select_results)
}

When __select_results contained a field with the same name as a table alias (e.g., both had email), the SELECT result would overwrite the table object, breaking the orderBy expression evaluation.

Solution

Simplified the context to use the namespaced row directly:

const orderByContext = row

This works because:

  1. Table aliases are top-level properties on row (e.g., row.email is the table object)
  2. SELECT results are in row.__select_results (e.g., row.__select_results.email is the field value)
  3. The replaceAggregatesByRefs function already transforms aggregate references to use __select_results namespace when needed

This prevents any conflict between table aliases and SELECT field names.

Additional Cleanup

Removed dead code in replaceAggregatesByRefs that attempted to support arbitrary SELECT alias references. The actual design pattern is aggregate matching: when you use an aggregate like count(orders.id) in HAVING or ORDER BY, it gets matched to the same aggregate in SELECT and replaced with a reference to the already-computed value. SELECT aliases themselves are never directly accessible in HAVING or ORDER BY callbacks.

Tests

Added comprehensive test coverage for alias/field name conflicts in order-by.test.ts.

@samwillis samwillis requested a review from KyleAMathews October 3, 2025 18:39
Copy link

changeset-bot bot commented Oct 3, 2025

🦋 Changeset detected

Latest commit: 57007e6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
@tanstack/db Patch
@tanstack/angular-db Patch
@tanstack/electric-db-collection Patch
@tanstack/query-db-collection Patch
@tanstack/react-db Patch
@tanstack/rxdb-db-collection Patch
@tanstack/solid-db Patch
@tanstack/svelte-db Patch
@tanstack/trailbase-db-collection Patch
@tanstack/vue-db Patch
todos Patch
@tanstack/db-example-react-todo Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

pkg-pr-new bot commented Oct 3, 2025

More templates

@tanstack/angular-db

npm i https://pkg.pr.new/@tanstack/angular-db@637

@tanstack/db

npm i https://pkg.pr.new/@tanstack/db@637

@tanstack/db-ivm

npm i https://pkg.pr.new/@tanstack/db-ivm@637

@tanstack/electric-db-collection

npm i https://pkg.pr.new/@tanstack/electric-db-collection@637

@tanstack/query-db-collection

npm i https://pkg.pr.new/@tanstack/query-db-collection@637

@tanstack/react-db

npm i https://pkg.pr.new/@tanstack/react-db@637

@tanstack/rxdb-db-collection

npm i https://pkg.pr.new/@tanstack/rxdb-db-collection@637

@tanstack/solid-db

npm i https://pkg.pr.new/@tanstack/solid-db@637

@tanstack/svelte-db

npm i https://pkg.pr.new/@tanstack/svelte-db@637

@tanstack/trailbase-db-collection

npm i https://pkg.pr.new/@tanstack/trailbase-db-collection@637

@tanstack/vue-db

npm i https://pkg.pr.new/@tanstack/vue-db@637

commit: 57007e6

Copy link
Contributor

github-actions bot commented Oct 3, 2025

Size Change: -60 B (-0.08%)

Total Size: 75.2 kB

Filename Size Change
./packages/db/dist/esm/query/compiler/group-by.js 2.04 kB -30 B (-1.45%)
./packages/db/dist/esm/query/compiler/order-by.js 1.21 kB -30 B (-2.43%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 943 B
./packages/db/dist/esm/collection/changes.js 1.01 kB
./packages/db/dist/esm/collection/events.js 660 B
./packages/db/dist/esm/collection/index.js 3.18 kB
./packages/db/dist/esm/collection/indexes.js 1.16 kB
./packages/db/dist/esm/collection/lifecycle.js 1.8 kB
./packages/db/dist/esm/collection/mutations.js 2.5 kB
./packages/db/dist/esm/collection/state.js 3.82 kB
./packages/db/dist/esm/collection/subscription.js 1.65 kB
./packages/db/dist/esm/collection/sync.js 1.42 kB
./packages/db/dist/esm/deferred.js 230 B
./packages/db/dist/esm/errors.js 3.1 kB
./packages/db/dist/esm/index.js 1.56 kB
./packages/db/dist/esm/indexes/auto-index.js 806 B
./packages/db/dist/esm/indexes/base-index.js 835 B
./packages/db/dist/esm/indexes/btree-index.js 2 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.21 kB
./packages/db/dist/esm/indexes/reverse-index.js 577 B
./packages/db/dist/esm/local-only.js 827 B
./packages/db/dist/esm/local-storage.js 2.02 kB
./packages/db/dist/esm/optimistic-action.js 294 B
./packages/db/dist/esm/proxy.js 3.86 kB
./packages/db/dist/esm/query/builder/functions.js 615 B
./packages/db/dist/esm/query/builder/index.js 4.04 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 938 B
./packages/db/dist/esm/query/compiler/evaluators.js 1.55 kB
./packages/db/dist/esm/query/compiler/expressions.js 631 B
./packages/db/dist/esm/query/compiler/index.js 2.04 kB
./packages/db/dist/esm/query/compiler/joins.js 2.52 kB
./packages/db/dist/esm/query/compiler/select.js 1.28 kB
./packages/db/dist/esm/query/ir.js 785 B
./packages/db/dist/esm/query/live-query-collection.js 340 B
./packages/db/dist/esm/query/live/collection-config-builder.js 2.69 kB
./packages/db/dist/esm/query/live/collection-subscriber.js 1.86 kB
./packages/db/dist/esm/query/optimizer.js 3.08 kB
./packages/db/dist/esm/SortedMap.js 1.24 kB
./packages/db/dist/esm/transactions.js 3 kB
./packages/db/dist/esm/utils.js 1.01 kB
./packages/db/dist/esm/utils/browser-polyfills.js 365 B
./packages/db/dist/esm/utils/btree.js 6.01 kB
./packages/db/dist/esm/utils/comparison.js 754 B
./packages/db/dist/esm/utils/index-optimization.js 1.73 kB

compressed-size-action::db-package-size

Copy link
Contributor

github-actions bot commented Oct 3, 2025

Size Change: 0 B

Total Size: 1.47 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 152 B
./packages/react-db/dist/esm/useLiveQuery.js 1.32 kB

compressed-size-action::react-db-package-size

@samwillis samwillis merged commit f623990 into main Oct 3, 2025
6 checks passed
@samwillis samwillis deleted the samwillis/fix-orderby-alias-bug branch October 3, 2025 18:53
@github-actions github-actions bot mentioned this pull request Oct 3, 2025
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.

Collection columns / .from() reference field bug
2 participants