Skip to content

Conversation

@KyleAMathews
Copy link
Collaborator

🎯 Changes

This PR enables the sync layer to optimize data fetching for lazy-loaded collections in join queries by passing orderBy and limit information to the loadSubset method.

Key Changes:

  1. New computeOrderByForAlias function in joins.ts:

    • Extracts orderBy and limit from a query when they reference fields belonging to a specific alias
    • Validates that all orderBy clauses reference fields from the lazy collection (not the active collection)
    • Calculates effective limit accounting for offset
    • Returns undefined if orderBy references fields from a different collection
  2. Enhanced join processing:

    • Computes orderBy and limit for the lazy collection using the new function
    • Passes orderBy and limit to requestSnapshot calls for lazy-loaded collections
    • Enables server-side sorting and pagination optimization in the sync layer
  3. Comprehensive test coverage:

    • Tests that orderBy is passed to lazy collection loadSubset in inner joins
    • Tests that both orderBy and limit are passed correctly
    • Tests that orderBy is NOT passed when it references the active collection (not the lazy one)
    • Tests join key filter (where clause) behavior in left joins

Behavior:

  • When a query has orderBy that references fields from the lazy collection in a join, this information is now passed to loadSubset
  • The sync layer can use this to optimize data fetching (e.g., fetch pre-sorted data from server)
  • If orderBy references fields from the active collection, it is not passed to the lazy collection's loadSubset
  • The limit is adjusted to account for offset when both are present

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

https://claude.ai/code/session_0152XUjMHqomrkmbCcZLJS9D

@changeset-bot
Copy link

changeset-bot bot commented Feb 12, 2026

⚠️ No Changeset found

Latest commit: ea23367

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@KyleAMathews KyleAMathews marked this pull request as draft February 12, 2026 21:54
@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 12, 2026

More templates

@tanstack/angular-db

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

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/electric-db-collection

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

@tanstack/offline-transactions

npm i https://pkg.pr.new/@tanstack/offline-transactions@1243

@tanstack/powersync-db-collection

npm i https://pkg.pr.new/@tanstack/powersync-db-collection@1243

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: ea23367

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

Size Change: +363 B (+0.39%)

Total Size: 92.4 kB

Filename Size Change
./packages/db/dist/esm/query/compiler/joins.js 2.47 kB +363 B (+17.23%) ⚠️
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 1.39 kB
./packages/db/dist/esm/collection/changes.js 1.22 kB
./packages/db/dist/esm/collection/events.js 388 B
./packages/db/dist/esm/collection/index.js 3.32 kB
./packages/db/dist/esm/collection/indexes.js 1.1 kB
./packages/db/dist/esm/collection/lifecycle.js 1.75 kB
./packages/db/dist/esm/collection/mutations.js 2.34 kB
./packages/db/dist/esm/collection/state.js 3.49 kB
./packages/db/dist/esm/collection/subscription.js 3.71 kB
./packages/db/dist/esm/collection/sync.js 2.41 kB
./packages/db/dist/esm/deferred.js 207 B
./packages/db/dist/esm/errors.js 4.7 kB
./packages/db/dist/esm/event-emitter.js 748 B
./packages/db/dist/esm/index.js 2.69 kB
./packages/db/dist/esm/indexes/auto-index.js 742 B
./packages/db/dist/esm/indexes/base-index.js 766 B
./packages/db/dist/esm/indexes/btree-index.js 2.17 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.1 kB
./packages/db/dist/esm/indexes/reverse-index.js 538 B
./packages/db/dist/esm/local-only.js 837 B
./packages/db/dist/esm/local-storage.js 2.1 kB
./packages/db/dist/esm/optimistic-action.js 359 B
./packages/db/dist/esm/paced-mutations.js 496 B
./packages/db/dist/esm/proxy.js 3.75 kB
./packages/db/dist/esm/query/builder/functions.js 733 B
./packages/db/dist/esm/query/builder/index.js 4.09 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 1.05 kB
./packages/db/dist/esm/query/compiler/evaluators.js 1.43 kB
./packages/db/dist/esm/query/compiler/expressions.js 430 B
./packages/db/dist/esm/query/compiler/group-by.js 1.81 kB
./packages/db/dist/esm/query/compiler/index.js 2.02 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.45 kB
./packages/db/dist/esm/query/compiler/select.js 1.06 kB
./packages/db/dist/esm/query/expression-helpers.js 1.43 kB
./packages/db/dist/esm/query/ir.js 673 B
./packages/db/dist/esm/query/live-query-collection.js 360 B
./packages/db/dist/esm/query/live/collection-config-builder.js 5.44 kB
./packages/db/dist/esm/query/live/collection-registry.js 264 B
./packages/db/dist/esm/query/live/collection-subscriber.js 2.42 kB
./packages/db/dist/esm/query/live/internal.js 145 B
./packages/db/dist/esm/query/optimizer.js 2.56 kB
./packages/db/dist/esm/query/predicate-utils.js 2.97 kB
./packages/db/dist/esm/query/subset-dedupe.js 921 B
./packages/db/dist/esm/scheduler.js 1.3 kB
./packages/db/dist/esm/SortedMap.js 1.3 kB
./packages/db/dist/esm/strategies/debounceStrategy.js 247 B
./packages/db/dist/esm/strategies/queueStrategy.js 428 B
./packages/db/dist/esm/strategies/throttleStrategy.js 246 B
./packages/db/dist/esm/transactions.js 2.9 kB
./packages/db/dist/esm/utils.js 924 B
./packages/db/dist/esm/utils/browser-polyfills.js 304 B
./packages/db/dist/esm/utils/btree.js 5.61 kB
./packages/db/dist/esm/utils/comparison.js 952 B
./packages/db/dist/esm/utils/cursor.js 457 B
./packages/db/dist/esm/utils/index-optimization.js 1.51 kB
./packages/db/dist/esm/utils/type-guards.js 157 B

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

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

Size Change: 0 B

Total Size: 3.7 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 225 B
./packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.17 kB
./packages/react-db/dist/esm/useLiveQuery.js 1.34 kB
./packages/react-db/dist/esm/useLiveSuspenseQuery.js 559 B
./packages/react-db/dist/esm/usePacedMutations.js 401 B

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

Two changes that work together to solve empty loadSubsetOptions when
using syncMode: 'on-demand' with joins:

1. Inner join active/lazy determination now respects orderBy

   Previously, inner joins always used a size heuristic to pick the
   active (fully-loaded) vs lazy (join-key-loaded) collection. Since
   both collections are empty at compile time, the heuristic was
   arbitrary (right side always won). Now, when the query has an
   orderBy referencing a specific source, that source becomes active.

   This means the orderBy collection's queryFn receives orderBy (and
   limit when present) in loadSubsetOptions, enabling efficient
   server-side sorting and pagination. The other collection loads
   matching rows via join keys.

2. Lazy collection's loadSubset receives orderBy/limit from the query

   When the join tap loads data for the lazy collection, it now passes
   the query's orderBy and limit (when they reference the lazy
   collection's fields) to requestSnapshot. This helps sync layers
   optimize fetching even when the active/lazy choice is fixed by
   join type (e.g., left join always has right side as lazy).

https://claude.ai/code/session_0152XUjMHqomrkmbCcZLJS9D
@KyleAMathews KyleAMathews force-pushed the claude/tanstack-db-sync-joins-f1gSY branch from f019ac2 to ea23367 Compare February 12, 2026 22:07
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.

2 participants