Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .changeset/cursor-pagination-loadsubset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
"@tanstack/db": patch
"@tanstack/electric-db-collection": patch
"@tanstack/query-db-collection": patch
---

Enhanced LoadSubsetOptions with separate cursor expressions and offset for flexible pagination.

**Changes:**

- Added `CursorExpressions` type with `whereFrom`, `whereCurrent`, and `lastKey` properties
- `LoadSubsetOptions.where` no longer includes cursor expressions - these are now passed separately via `cursor`
- Added `offset` to `LoadSubsetOptions` for offset-based pagination support
- Electric sync layer now makes two parallel `requestSnapshot` calls when cursor is present:
- One for `whereCurrent` (all ties at boundary, no limit)
- One for `whereFrom` (rows after cursor, with limit)
- Query collection serialization now includes `offset` for query key generation

**Benefits:**

- Sync layers can choose between cursor-based or offset-based pagination strategies
- Electric can efficiently handle tie-breaking with two targeted requests
- Better separation of concerns between filtering (`where`) and pagination (`cursor`/`offset`)
23 changes: 23 additions & 0 deletions .changeset/deterministic-collection-ordering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
"@tanstack/db": patch
---

Ensure deterministic iteration order for collections and indexes.

**SortedMap improvements:**

- Added key-based tie-breaking when values compare as equal, ensuring deterministic ordering
- Optimized to skip value comparison entirely when no comparator is provided (key-only sorting)
- Extracted `compareKeys` utility to `utils/comparison.ts` for reuse

**BTreeIndex improvements:**

- Keys within the same indexed value are now returned in deterministic sorted order
- Optimized with fast paths for empty sets and single-key sets to avoid unnecessary allocations

**CollectionStateManager changes:**

- Collections now always use `SortedMap` for `syncedData`, ensuring deterministic iteration order
- When no `compare` function is provided, entries are sorted by key only

This ensures that live queries with `orderBy` and `limit` produce stable, deterministic results even when multiple rows have equal sort values.
9 changes: 9 additions & 0 deletions .changeset/fix-livequery-loading-status-ondemand.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@tanstack/db": patch
---

fix(db): show loading status during initial loadSubset for on-demand sync

Fixed an issue where live queries using on-demand sync mode would immediately show `isLoading: false` and `status: 'ready'` even while the initial data was still being fetched. Now the live query correctly shows `isLoading: true` and `status: 'loading'` until the first `loadSubset` completes.

This ensures that UI components can properly display loading indicators while waiting for the initial data to arrive from on-demand sync sources. Subsequent `loadSubset` calls (e.g., from pagination or windowing) do not affect the ready status.
18 changes: 18 additions & 0 deletions .changeset/multi-column-orderby-loadsubset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"@tanstack/db": patch
---

Enhanced multi-column orderBy support with lazy loading and composite cursor optimization.

**Changes:**

- Create index on first orderBy column even for multi-column orderBy queries, enabling lazy loading with first-column ordering
- Pass multi-column orderBy to loadSubset with precise composite cursors (e.g., `or(gt(col1, v1), and(eq(col1, v1), gt(col2, v2)))`) for backend optimization
- Use wide bounds (first column only) for local index operations to ensure no rows are missed
- Use precise composite cursor for sync layer loadSubset to minimize data transfer

**Benefits:**

- Multi-column orderBy queries with limit now support lazy loading (previously disabled)
- Sync implementations (like Electric) can optimize queries using composite indexes on the backend
- Local collection uses first-column index efficiently while backend gets precise cursor
9 changes: 9 additions & 0 deletions .changeset/stable-order-tiebreaker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@tanstack/db-ivm": patch
---

Use row keys for stable tie-breaking in ORDER BY operations instead of hash-based object IDs.

Previously, when multiple rows had equal ORDER BY values, tie-breaking used `globalObjectIdGenerator.getId(key)` which could produce hash collisions and wasn't stable across page reloads for object references. Now, the row key (which is always `string | number` and unique per row) is used directly for tie-breaking, ensuring deterministic and stable ordering.

This also simplifies the internal `TaggedValue` type from a 3-tuple `[K, V, Tag]` to a 2-tuple `[K, V]`, removing unnecessary complexity.
Loading
Loading