8000 feat(sqlite): type the full-text search functions by colinhacks · Pull Request #32 · colinhacks/reylo · GitHub
[go: up one dir, main page]

Skip to content

feat(sqlite): type the full-text search functions - #32

Merged
colinhacks merged 2 commits into
mainfrom
sqlite-fts5-functions
Oct 22, 2026
Merged

colinhacks merged 2 commits into
mainfrom
sqlite-fts5-functions

Conversation

@colinhacks
Copy link
Copy Markdown
Owner

FTS5's bm25 is now typed number, highlight and snippet string | null, and FTS4's offsets string and matchinfo Uint8Array. Each was unknown:

select rowid as id, highlight(docs, 1, '<b>', '</b>') as hit, bm25(docs) as rank
from docs where docs match :q order by rank
-- before: { id: number; hit: unknown; rank: unknown }[]
-- after:  { id: number; hit: string | null; rank: number }[]

A parameter passed as highlight's column (integer) or markers (text), or as a bm25 weight (real), is typed too. Inside built JSON each nests as the value it is.

Why these types. Measured on SQLite 3.53.4 over rows with a NULL in each column: highlight and FTS5's snippet return NULL exactly where the column they read is NULL; bm25 is a real on every row, 0 where no MATCH ranks it; offsets and matchinfo answer every row. FTS4's snippet shares the name, so snippet stays nullable.

Checks

  • Native test the_full_text_functions_are_typed in engine/sqlite.
  • The sqlite_fts oracle case gains three statements (ranked and highlighted FTS5 matches, the functions with no MATCH, an FTS4 table), run over seeded edge values with none left unchecked.
  • packages/sqlite/engine.wasm rebuilt.
  • The SQLite reference page gains a "Full-text search" rule.

bm25 is a real, highlight and snippet are text that may be null, and FTS4's offsets and matchinfo are text and a blob; each was unknown.
Copilot AI balanced review requested due to automatic review settings October 22, 2026 21:06
@vercel
vercel Bot commented Oct 22, 2026 •
Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
reylo Ready Ready Preview Oct 22, 2026 9:20pm UTC

Request Review

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

bm25 with weight arguments can return NULL, but it is typed as never null.

Reviewed changes

I reviewed the whole PR: the FTS function typing in the SQLite analyzer, its parameter contexts, the native and oracle tests, and the docs rule.

  • Result types: bm25 is a non-null real. highlight and snippet are nullable text. offsets is a non-null text and matchinfo a non-null blob. All five are in PLAIN, so they carry no JSON subtype.
  • Parameter contexts: highlight's column parameter is typed integer and its marker parameters text. A bm25 weight is typed real.
  • Tests: a native test the_full_text_functions_are_typed, three new sqlite_fts oracle statements and an FTS4 notes table in setup.sql.
  • Docs: a "Full-text search" rule on the SQLite reference page.

I tested the FTS4 and no-MATCH claims on SQLite 3.45.1 and they hold. offsets, matchinfo and FTS4 snippet return '' or an empty blob, never NULL. FTS5 highlight and snippet are NULL exactly where their column is.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread engine/sqlite/src/sqlite.rs Resolved
An infinite or overflowing weight makes the score NaN, which SQLite returns as NULL.
@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found. The weighted bm25 feedback is addressed cleanly.

Reviewed changes

I reviewed 0384c7d, the single commit since the prior review.

  • Weighted bm25 nullable: bm25(t) stays a non-null real. With weight arguments it is now a nullable real, chosen by the argument count the same way json_type and json_remove already do it.
  • Tests and docs follow: the native test asserts weighted nullable, the sqlite_fts expectation reads weighted: real?, and the docs rule gains a bm25(docs, 1e999, 1.0) → null pair. packages/sqlite/engine.wasm is rebuilt.

I checked the new docs pair on SQLite 3.45.1. bm25(docs, 1e999, 1.0) is NULL on a row that matches once in the weighted column, and bm25(docs) is a real on every row, with or without MATCH.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@colinhacks
colinhacks merged commit 900f3e7 into main Oct 22, 2026
4 checks passed
@colinhacks
colinhacks deleted the sqlite-fts5-functions branch October 22, 2026 21:23
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

0