Skip to content

feat: improve indexes - #20

Merged
quolpr merged 4 commits into
mainfrom
quolpr/improve-indexes
Aug 7, 2026
Merged

feat: improve indexes#20
quolpr merged 4 commits into
mainfrom
quolpr/improve-indexes

Conversation

@quolpr

@quolpr quolpr commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Summary by CodeRabbit

  • New Features

    • Added compact binary sort-key storage for SQLite and IndexedDB.
    • Added direct primary-key lookups, improved large selector handling, and automatic migration from legacy text sort keys.
    • Enabled shared physical indexes for compatible unique and ordered indexes.
  • Bug Fixes

    • Added validation for duplicate or conflicting index definitions.
    • Improved deterministic ordering with ID tie-breaking and deduplicated repeated exact-ID results.
    • Rejected incomplete exact-hash queries.
  • Documentation

    • Expanded guidance for index behavior, storage formats, migrations, and driver-specific query handling.

@codesandbox

codesandbox Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@netlify

netlify Bot commented Aug 7, 2026

Copy link
Copy Markdown

Deploy Preview for hyperdb ready!

Name Link
🔨 Latest commit d9bbdf1
🔍 Latest deploy log https://app.netlify.com/projects/hyperdb/deploys/6a75ef1d1fbe94000843d208
😎 Deploy Preview https://deploy-preview-20--hyperdb.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@quolpr, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 30 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 35a5618b-ecba-4e4f-991e-0f0045d2ce1c

📥 Commits

Reviewing files that changed from the base of the PR and between c05e915 and d9bbdf1.

📒 Files selected for processing (9)
  • packages/hyperdb-demo/CHANGELOG.md
  • packages/hyperdb-devtool/CHANGELOG.md
  • packages/hyperdb/CHANGELOG.md
  • packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/persistent-index-plan.test.ts
  • packages/hyperdb/src/hyperdb/drivers/persistent-index-plan.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/async-sql-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sql-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-common.ts
📝 Walkthrough

Walkthrough

The change validates index definitions, introduces shared persistent physical indexes, replaces textual SQLite sort keys with binary keys, and updates SQLite and IndexedDB storage, scans, migrations, tests, and documentation.

Changes

Persistent index storage

Layer / File(s) Summary
Index definition validation
packages/hyperdb/src/hyperdb/schema/table.ts, packages/hyperdb/src/hyperdb/schema/table.test.ts, packages/hyperdb-doc/src/content/docs/database/...
Index names and definitions now undergo duplicate and prefix validation. Compatible uniqhash and B-tree indexes can share a column.
Physical index mapping and binary sort keys
packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-common.ts, packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-sort-key.ts, packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-sort-key.test.ts, packages/hyperdb/src/hyperdb/runtime/db.test.ts
Logical indexes now map to persistent physical indexes. SQLite sort keys use compact binary encodings, and tests cover ordering and binary representation.
SQLite physical storage and migration
packages/hyperdb/src/hyperdb/drivers/sqlite/..., packages/hyperdb-doc/src/content/docs/runtime/drivers.md, README.md
SQLite uses versioned BLOB sort-key columns, supports legacy-key migration, primary-key IN lookups, balanced OR predicates, and shared physical indexes.
IndexedDB physical storage and scans
packages/hyperdb/src/hyperdb/drivers/idb/..., packages/hyperdb-doc/src/content/docs/runtime/drivers.md
IndexedDB stores ArrayBuffer keys, derives native indexes from persistent physical indexes, and adds direct primary-key scan handling.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Schema
  participant PhysicalIndexResolver
  participant SQLiteDriver
  participant SQLiteStorage
  Schema->>PhysicalIndexResolver: validate and resolve index definitions
  PhysicalIndexResolver-->>SQLiteDriver: persistent physical index metadata
  SQLiteDriver->>SQLiteStorage: store or migrate binary BLOB sort keys
  SQLiteDriver->>SQLiteStorage: execute range or primary-key IN query
  SQLiteStorage-->>SQLiteDriver: matching records
Loading
sequenceDiagram
  participant Schema
  participant PhysicalIndexResolver
  participant IndexedDBDriver
  participant IndexedDBObjectStore
  Schema->>PhysicalIndexResolver: validate and resolve index definitions
  PhysicalIndexResolver-->>IndexedDBDriver: persistent physical index names
  IndexedDBDriver->>IndexedDBObjectStore: scan native index or fetch primary-key matches
  IndexedDBObjectStore-->>IndexedDBDriver: ordered records
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title identifies indexes as the main area of change and accurately summarizes the pull request at a broad level.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch quolpr/improve-indexes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.browser.test.ts (1)

162-162: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Assert the encoded bytes, not only the container type.

Line 162 passes for an empty or incorrect ArrayBuffer. Compare the stored bytes with the expected byCount sort key, or decode the key and assert its value. This keeps the test covering the persisted binary-index contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.browser.test.ts` at line
162, Strengthen the assertion in the relevant IndexedDB persistence test around
stored.indexes.byCount so it verifies the encoded bytes or decodes and compares
the key to the expected byCount sort key, rather than only checking ArrayBuffer
type. Preserve the existing persistence assertions while ensuring an empty or
incorrect buffer fails the test.
packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-sort-key.ts (1)

134-154: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The variable-length integer encoding preserves order. Add the bounds to the comment.

The lead-byte ranges are disjoint and increasing across lengths: 0x010x7f, 0xc20xdf, 0xe00xef, and 0xf0. Continuation bytes carry six bits each in big-endian order, so the encoding is bytewise monotone. The 4-byte branch carries 22 bits and therefore only supports values up to 0x3fffff. Both callers stay inside that limit (charCodeAt(...) + 1 reaches 0x10000, byte + 1 reaches 0x100), but the function does not reject larger input. State the supported range in the comment so a future caller does not silently produce a wrong key.

♻️ Proposed comment update
 // Encodes a positive integer with the same bytewise order as its numeric
-// value. Zero is reserved as a terminator, so callers pass values >= 1.
+// value. Zero is reserved as a terminator, so callers pass values >= 1.
+// The encoding supports values in the range 1..0x3fffff.
 function encodePositiveInteger(value: number): number[] {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-sort-key.ts` around lines
134 - 154, Update the comment above encodePositiveInteger to document that it
supports positive values from 1 through 0x3fffff inclusive, with zero reserved
as the terminator; note that callers must remain within this range.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.ts`:
- Around line 895-924: Update the primary-key branch around
isPrimaryKeyBackedIndex to validate every equality condition like SQLite,
throwing “Primary-key index ${indexName} requires string IDs” when a condition
is not for id or its value is not a string; then collect unique ids before
issuing store.get requests so each record is returned once. Remove the discarded
createSortKeyRanges call, including any now-unused dependency, since this path
does not need to construct sort-key ranges.

In `@packages/hyperdb/src/hyperdb/drivers/sqlite/sql-driver.ts`:
- Around line 451-452: Update the generated-name parsing in
packages/hyperdb/src/hyperdb/drivers/sqlite/sql-driver.ts lines 451-452 and
packages/hyperdb/src/hyperdb/drivers/sqlite/async-sql-driver.ts lines 853-854 to
select and remove only one matching suffix, preferring the v2 suffix before the
legacy suffix, rather than chaining both replacements. Add regression tests in
both driver suites for logical index names ending in _sort_key, verifying
correct physical index lookup and scan ordering.

In `@packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-common.ts`:
- Around line 368-378: Update validateHashBounds to reject empty rawBounds and
any bound without gte before the primary-key handling in
buildSortKeyWhereClause. Perform this validation before the existing string-ID
check so no-condition hash/uniqhash selectors cannot produce an empty id list or
WHERE id IN ().

---

Nitpick comments:
In `@packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.browser.test.ts`:
- Line 162: Strengthen the assertion in the relevant IndexedDB persistence test
around stored.indexes.byCount so it verifies the encoded bytes or decodes and
compares the key to the expected byCount sort key, rather than only checking
ArrayBuffer type. Preserve the existing persistence assertions while ensuring an
empty or incorrect buffer fails the test.

In `@packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-sort-key.ts`:
- Around line 134-154: Update the comment above encodePositiveInteger to
document that it supports positive values from 1 through 0x3fffff inclusive,
with zero reserved as the terminator; note that callers must remain within this
range.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3cfb6eeb-4c39-4337-a872-43aadf48f3d3

📥 Commits

Reviewing files that changed from the base of the PR and between 95cc96e and 99e99b4.

📒 Files selected for processing (16)
  • README.md
  • packages/hyperdb-doc/src/content/docs/database/indexes.md
  • packages/hyperdb-doc/src/content/docs/database/schemas.md
  • packages/hyperdb-doc/src/content/docs/runtime/drivers.md
  • packages/hyperdb-doc/src/content/docs/start/llm-cheat-sheet.md
  • packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.browser.test.ts
  • packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/async-sql-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/driver-edge-cases.test.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sql-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-common.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-sort-key.test.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-sort-key.ts
  • packages/hyperdb/src/hyperdb/runtime/db.test.ts
  • packages/hyperdb/src/hyperdb/schema/table.test.ts
  • packages/hyperdb/src/hyperdb/schema/table.ts

Comment thread packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.ts
Comment thread packages/hyperdb/src/hyperdb/drivers/sqlite/sql-driver.ts Outdated
Comment thread packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-common.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/hyperdb-doc/src/content/docs/database/indexes.md (1)

139-142: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Document when id is appended for non-unique indexes.

persistentPhysicalIndexes adds id only for btree indexes; uniqhash indexes include only the hash columns. The current wording makes it sound like id is part of the non-unique key tuple for uniqhash too, which is not true.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/hyperdb-doc/src/content/docs/database/indexes.md` around lines 139 -
142, Update the index documentation to state that HyperDB appends id only to
non-unique btree indexes that do not already end in id; clarify that uniqhash
indexes contain only their hash columns. Preserve the explanation of
deterministic ordering for btree indexes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/hyperdb-doc/src/content/docs/database/indexes.md`:
- Around line 139-142: Update the index documentation to state that HyperDB
appends id only to non-unique btree indexes that do not already end in id;
clarify that uniqhash indexes contain only their hash columns. Preserve the
explanation of deterministic ordering for btree indexes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dbbd31ed-7723-4baf-8718-14b79b4d87ce

📥 Commits

Reviewing files that changed from the base of the PR and between 99e99b4 and c05e915.

📒 Files selected for processing (12)
  • README.md
  • packages/hyperdb-doc/src/content/docs/database/indexes.md
  • packages/hyperdb-doc/src/content/docs/runtime/drivers.md
  • packages/hyperdb-doc/src/content/docs/start/llm-cheat-sheet.md
  • packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.browser.test.ts
  • packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/async-sql-driver.test.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/async-sql-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/driver-edge-cases.test.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sql-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-common.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-sort-key.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/hyperdb-doc/src/content/docs/start/llm-cheat-sheet.md
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sql-driver.ts
  • README.md
  • packages/hyperdb/src/hyperdb/drivers/sqlite/async-sql-driver.ts
  • packages/hyperdb-doc/src/content/docs/runtime/drivers.md
  • packages/hyperdb/src/hyperdb/drivers/idb/idb-driver.ts
  • packages/hyperdb/src/hyperdb/drivers/sqlite/sqlite-common.ts

@quolpr
quolpr merged commit 194a110 into main Aug 7, 2026
9 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.

1 participant