Skip to content

feat(store): add sqlite record resolution - #80

Merged
ian-pascoe merged 4 commits into
mainfrom
issue-62-sqlite-record-resolution
Aug 11, 2026
Merged

feat(store): add sqlite record resolution#80
ian-pascoe merged 4 commits into
mainfrom
issue-62-sqlite-record-resolution

Conversation

@ian-pascoe

@ian-pascoe ian-pascoe commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add Drizzle-independent SQLite table, column, type, ROWID, and generated-column metadata helpers
  • add the synchronous adapter-facing SQLite Record resolver with immutable assets and strict codecs
  • export the public SQLite authoring and adapter subpaths, document usage, and add a release changeset

Verification

  • pnpm --filter @commissary/store exec vitest run test/sql/sqlite/record.test.ts
  • pnpm --filter @commissary/store typecheck
  • pnpm run verify
  • pnpm run pack:check

Closes #62

Summary by CodeRabbit

  • New Features

    • Added SQLite-specific record definitions, built-in value types, validated codecs, and synchronous record resolution.
    • Added immutable runtime metadata, overrides, clear validation errors, and public SQLite adapter exports.
    • Added shared SQL metadata validation and canonical Base64 handling.
  • Bug Fixes

    • SQLite text values now reject NUL characters and unpaired Unicode surrogates.
    • Improved validation for SQL metadata, defaults, generated columns, and custom values.
  • Documentation

    • Added guidance for defining and resolving SQLite records.
  • Tests

    • Added comprehensive coverage for metadata, codecs, overrides, constraints, and validation.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 47 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 119b4ca9-b2f2-46f4-9251-b2fe8b9c5d1b

📥 Commits

Reviewing files that changed from the base of the PR and between ad83fb8 and 1490669.

📒 Files selected for processing (4)
  • packages/store/src/sql/contract-object.ts
  • packages/store/src/sql/sqlite/record-resolver.ts
  • packages/store/test/sql/contract-object.test.ts
  • packages/store/test/sql/sqlite/record.test.ts
📝 Walkthrough

Walkthrough

Added SQLite-specific record metadata, direct and custom codecs, validation utilities, immutable runtime resolution assets, adapter exports, documentation, shared SQL contract utilities, and dialect migrations. The synchronous resolver applies overrides and aggregates definition errors without I/O.

Changes

SQLite record specialization

Layer / File(s) Summary
Shared SQL contracts and validation
packages/store/src/sql/base64.ts, packages/store/src/sql/contract-object.ts, packages/store/src/sql/opaque-format.ts, packages/store/src/sql/definition-statement.ts, packages/store/src/sql/record.ts, packages/store/src/sql/statement.ts
Added shared immutable snapshots, opaque metadata formats, canonical Base64, contract-key checks, statement validation, and portable type helpers.
Shared validation adoption
packages/store/src/sql/mysql/*, packages/store/src/sql/postgres/*, packages/store/src/sql/record-catalog-resolver.ts
Updated MySQL and PostgreSQL code to use the shared contract, metadata, statement, portable-type, custom-value, and Base64 utilities.
SQLite metadata and physical types
packages/store/src/sql/sqlite/record.ts, packages/store/src/sql/sqlite/resolution-types.ts, packages/store/src/sql/sqlite/sqlite-contract.ts, packages/store/src/sql/sqlite/metadata.ts, packages/store/src/sql/sqlite/column-codecs.ts, packages/store/src/sql/sqlite/column-type-resolver.ts, packages/store/src/sql/sqlite/column-resolution.ts
Added SQLite metadata contracts, constructors, direct and custom types, strict codecs, physical-type resolution, default validation, ROWID handling, and generated-column validation.
Synchronous record resolution
packages/store/src/sql/sqlite/record-resolver.ts, packages/store/src/sql/sqlite/adapter.ts, packages/store/test/sql/sqlite/record.test.ts
Added override-aware resolution into frozen runtime assets, aggregate definition errors, adapter-facing exports, and coverage for codecs, metadata, naming, constraints, opaque formats, and overrides.
Package surface and specification
packages/store/package.json, packages/store/src/sql/sqlite/index.ts, packages/store/README.md, docs/specs/sql-store.md, .changeset/fair-tables-resolve.md
Added SQLite package entry points, public exports, resolver documentation, a SQLite text contract update, and a minor-release changeset.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

Poem

A rabbit checks each frozen row,
While SQLite codecs flow.
Names and defaults pass the gate,
Errors gather, clear and straight.
“Hop,” says the resolver bright,
“Immutable plans are just right.”

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes broad PostgreSQL, MySQL, and shared SQL utility refactors that are not required by the SQLite resolution scope in [#62]. Move the unrelated cross-dialect refactors into a separate pull request, or document their direct necessity for the SQLite implementation.
Docstring Coverage ⚠️ Warning Docstring coverage is 21.37% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: adding SQLite record resolution to the store package.
Description check ✅ Passed The description includes Summary and Verification details and documents tests, documentation, and the changeset, but omits the Release checklist section.
Linked Issues check ✅ Passed The changes implement the SQLite metadata helpers, synchronous resolver, codecs, exports, tests, documentation, changeset, and verification required by [#62].
✨ 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 issue-62-sqlite-record-resolution

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

🤖 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/store/src/sql/sqlite/column-codecs.ts`:
- Around line 210-215: Update the text codec’s encode/decode validation and the
json-blob codec’s payload validation to reject strings containing unpaired
surrogates, while preserving the existing NUL checks. Reuse the established
isValidSqliteName-style validation or String.prototype.isWellFormed when
supported, ensuring invalid values fail before UTF-8 encoding or storage.

In `@packages/store/src/sql/sqlite/record-resolver.ts`:
- Around line 80-113: Extract the shared SQLite name-validation flow from the
table and column resolver blocks into one helper, parameterized by metadata
value, winning name, issue path, and message factory. Have the helper validate
an explicit name candidate, resolve the winning-name comparison, and suppress
the duplicate issue when the winning name is that candidate. Replace both table
and column logic with the helper while preserving their distinct labels, path
tails, and messages.

In `@packages/store/test/sql/sqlite/record.test.ts`:
- Around line 533-638: Add a dedicated record in the test fixture catalog that
uses nullableStringField with a SQLite column configured with notNull: true,
ensuring it reaches the explicit nullability-conflict validation rather than the
ROWID path. Extend the expected issue code and path arrays in
resolveSqliteRecords coverage with the new invalid-database-options entry in
catalog order, pointing to that record’s notNull configuration.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 292cd824-3049-4a4a-a75c-c408fc82a94c

📥 Commits

Reviewing files that changed from the base of the PR and between 9484564 and 5bcd0db.

📒 Files selected for processing (14)
  • .changeset/fair-tables-resolve.md
  • packages/store/README.md
  • packages/store/package.json
  • packages/store/src/sql/sqlite/adapter.ts
  • packages/store/src/sql/sqlite/column-codecs.ts
  • packages/store/src/sql/sqlite/column-resolution.ts
  • packages/store/src/sql/sqlite/column-type-resolver.ts
  • packages/store/src/sql/sqlite/index.ts
  • packages/store/src/sql/sqlite/metadata.ts
  • packages/store/src/sql/sqlite/record-resolver.ts
  • packages/store/src/sql/sqlite/record.ts
  • packages/store/src/sql/sqlite/resolution-types.ts
  • packages/store/src/sql/sqlite/sqlite-contract.ts
  • packages/store/test/sql/sqlite/record.test.ts

Comment thread packages/store/src/sql/sqlite/column-codecs.ts
Comment thread packages/store/src/sql/sqlite/record-resolver.ts Outdated
Comment thread packages/store/test/sql/sqlite/record.test.ts
@ian-pascoe

Copy link
Copy Markdown
Contributor Author

Implemented the cross-dialect SQL Record utility refactor in ad83fb8.

  • Added shared contract-object snapshot/key guards, opaque metadata formats, parameter-free definition Statement validation, canonical RFC 4648 Base64 codecs, portable type recognition, and custom encoded-value checks.
  • Migrated PostgreSQL, MySQL, and SQLite Record helpers, codecs, metadata readers, type resolvers, and Record resolvers to the shared owners.
  • Preserved dialect-specific naming, codecs, generated-column, identity/ROWID, issue ordering, and exact error behavior.
  • Added focused shared utility contract tests.

Verification:

  • pnpm --filter @commissary/store exec vitest run test/sql: 11 files, 101 tests passed.
  • pnpm --filter @commissary/store typecheck: passed.
  • pnpm run verify: 15/15 tasks passed.
  • pnpm run pack:check: 10/10 tasks passed.

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/store/src/sql/sqlite/record-resolver.ts (1)

338-344: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject generated columns in SQLite primary keys.

resolveSqlPrimaryKey checks only notNull, so a generated column enters primaryKey without an issue. Add SQLite-specific validation and regression coverage.

🤖 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/store/src/sql/sqlite/record-resolver.ts` around lines 338 - 344,
Update resolveSqlPrimaryKey and its SQLite call path to reject generated columns
used in primary keys, adding an issue when such a column is encountered rather
than including it in primaryKey. Add regression coverage for generated
primary-key columns while preserving valid non-generated primary keys.
🤖 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/store/src/sql/contract-object.ts`:
- Around line 31-40: Update the snapshot copy loop in
packages/store/src/sql/contract-object.ts#L31-L40 to define each copied key as
an own data property rather than calling Reflect.set, preserving an own
__proto__ key without changing the snapshot prototype. Add a regression test in
packages/store/test/sql/contract-object.test.ts#L43-L75 that snapshots an object
with an own __proto__ property and asserts the snapshot retains it as an own
property.

---

Outside diff comments:
In `@packages/store/src/sql/sqlite/record-resolver.ts`:
- Around line 338-344: Update resolveSqlPrimaryKey and its SQLite call path to
reject generated columns used in primary keys, adding an issue when such a
column is encountered rather than including it in primaryKey. Add regression
coverage for generated primary-key columns while preserving valid non-generated
primary keys.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 27ffe577-8625-4a2c-9d5f-acdc34ce8109

📥 Commits

Reviewing files that changed from the base of the PR and between 5bcd0db and ad83fb8.

📒 Files selected for processing (33)
  • docs/specs/sql-store.md
  • packages/store/src/sql/base64.ts
  • packages/store/src/sql/contract-object.ts
  • packages/store/src/sql/definition-statement.ts
  • packages/store/src/sql/mysql/column-codecs.ts
  • packages/store/src/sql/mysql/column-resolution.ts
  • packages/store/src/sql/mysql/column-type-resolver.ts
  • packages/store/src/sql/mysql/metadata.ts
  • packages/store/src/sql/mysql/mysql-contract.ts
  • packages/store/src/sql/mysql/record-resolver.ts
  • packages/store/src/sql/mysql/record.ts
  • packages/store/src/sql/opaque-format.ts
  • packages/store/src/sql/postgres/column-codecs.ts
  • packages/store/src/sql/postgres/column-type-resolver.ts
  • packages/store/src/sql/postgres/metadata.ts
  • packages/store/src/sql/postgres/record-resolver.ts
  • packages/store/src/sql/postgres/record.ts
  • packages/store/src/sql/record-catalog-resolver.ts
  • packages/store/src/sql/record.ts
  • packages/store/src/sql/sqlite/column-codecs.ts
  • packages/store/src/sql/sqlite/column-resolution.ts
  • packages/store/src/sql/sqlite/column-type-resolver.ts
  • packages/store/src/sql/sqlite/metadata.ts
  • packages/store/src/sql/sqlite/record-resolver.ts
  • packages/store/src/sql/sqlite/record.ts
  • packages/store/src/sql/sqlite/sqlite-contract.ts
  • packages/store/src/sql/statement.ts
  • packages/store/test/sql/base64.test.ts
  • packages/store/test/sql/contract-object.test.ts
  • packages/store/test/sql/definition-statement.test.ts
  • packages/store/test/sql/opaque-format.test.ts
  • packages/store/test/sql/record-utilities.test.ts
  • packages/store/test/sql/sqlite/record.test.ts
💤 Files with no reviewable changes (1)
  • packages/store/src/sql/mysql/mysql-contract.ts

Comment thread packages/store/src/sql/contract-object.ts
@ian-pascoe

Copy link
Copy Markdown
Contributor Author

Addressed the outside-diff SQLite primary-key finding in 1490669.

resolveSqlitePrimaryKey now reports invalid-primary-key at the exact primary-key tuple index for each resolved generated column and excludes that column from the primary-key asset. A regression test rejects a generated key while confirming an ordinary key still resolves unchanged.

Also fixed the inline __proto__ snapshot finding. Focused tests pass (2 files, 17 tests), pnpm run verify passes (15/15 tasks), and pnpm run pack:check passes (10/10 tasks).

@ian-pascoe
ian-pascoe merged commit 8afad5a into main Aug 11, 2026
9 checks passed
@ian-pascoe
ian-pascoe deleted the issue-62-sqlite-record-resolution branch August 11, 2026 10:04
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.

Implement SQLite Record resolution

1 participant