Skip to content

feat(history): filter, sort and page location queries natively - #64

Merged
The-PatientZero merged 6 commits into
mainfrom
feat/native-history-queries
Nov 4, 2026
Merged

The-PatientZero merged 6 commits into
mainfrom
feat/native-history-queries

Conversation

@The-PatientZero

Copy link
Copy Markdown
Collaborator

Description

Closes #47.

Locus.location.query(...) now filters, sorts and pages on the native side, so a limited query returns only the selected page to Dart instead of loading the whole table.

  • Channel. A new private queryLocations method-channel call carries UTC epoch-microsecond bounds and every current predicate (time range, accuracy, moving state, bounding box). Native code applies all of them before LIMIT/OFFSET. getLocations is unchanged.
  • Version mismatch. When the Dart and native sides come from different versions, the query fails with UNSUPPORTED_NATIVE_QUERY and asks for a host rebuild. It never falls back to fetching all history.
  • Android. Queries are pushed into SQL with normalized columns and run on a single background thread.
  • iOS.
    • Queries use a separate read-only connection, so they never delay location writes.
    • Time windows and paging use the indexed timestamp column. Rows whose stored timestamp is not canonical are parsed on the fly.
    • A record that cannot be read is logged and excluded before paging instead of failing the query.
    • Releasing the last storage reference no longer dispatches synchronously onto its own database queue.
  • Example app. The Stored Locations demo card gains filters, fixed-window paging, input validation and retry states.
  • Docs. New guide doc/guides/querying-history.md, plus updates to the error-code reference and the testing guide.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Chore / Documentation / Refactor

Native Changes

  • Android (Java/Gradle)
  • iOS (Swift/Podspec)
  • Dart/Flutter only

Testing Checklist

  • flutter analyze passes
  • flutter test passes (Unit Tests)
  • cd example && flutter build apk --debug (Android Build)
  • cd example && flutter build ios --no-codesign --debug (iOS Build)
  • Verified on physical device (required for background/geolocation testing)

Also run:

  • Android. Unit tests and lint pass. ConfigSnapshotInstrumentation passes 10 of 10 checks on an API 36 emulator, including real-SQLite history checks for filtering before paging, sort order, inclusive edges, timestamp rounding and unbounded ranges.
  • iOS. All 75 Swift tests pass under both the Locus and locus module names.
  • Dart. 807 Dart tests and 8 example widget tests pass.
  • Manual iOS timing on 100,000 records. Newest page: 148 ms. A 1,000-second window: 92 ms. A moving-state filter over the whole history: about 1.5 s. A write issued during a long query: 2 ms.

Screenshots / Diagnostics

N/A

Checklist

  • I have followed the Contributing Guidelines.
  • My code follows the style guidelines of this project.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation.
  • My changes generate no new warnings.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • Any dependent changes have been merged and published in downstream modules.

WeOrbis Core Team added 5 commits November 4, 2026 11:03
queryLocations previously fetched limit+offset rows into Dart and filtered
them there, which returned wrong pages whenever filters excluded rows and
loaded whole histories into the Dart heap for unpaged queries.

A private queryLocations channel now applies every predicate before
LIMIT/OFFSET in SQLite on Android and iOS. On iOS, queries run on a separate
read-only connection so long scans never block location writes, rows whose
payload timestamp matches the indexed timestamp column filter and sort on
that column, and unreadable rows are excluded before paging. getLocations is
unchanged.

Closes #47
@The-PatientZero
The-PatientZero force-pushed the feat/native-history-queries branch from 943013b to dfb37d5 Compare November 4, 2026 10:03
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Switch the history card and its test to material_ui to match the example's migration in #63.
@The-PatientZero
The-PatientZero merged commit c5b4b4a into main Nov 4, 2026
14 checks passed
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.

Native-side pagination + filtering for queryLocations (avoid loading entire table into Dart heap)

2 participants