Skip to content

Declarative vector/full-text/hybrid search, at-rest encryption docs, plural table names#1

Merged
arthurpro merged 5 commits into
mainfrom
feat/search-naming
Jun 18, 2026
Merged

Declarative vector/full-text/hybrid search, at-rest encryption docs, plural table names#1
arthurpro merged 5 commits into
mainfrom
feat/search-naming

Conversation

@arthurpro

Copy link
Copy Markdown
Member

Summary

  • Declarative search — vector, full-text (FTS5), and hybrid (RRF) indexes declared via vec:/fts:/fts5: struct tags or a SearchIndexes() method. New dialect.SearchProvisioner/SearchRowSyncer capabilities emit the DDL/sync SQL, so dialect stays free of orm/session deps. Trigger-sync (all writes) and hook-sync (ORM writes only); FTS5 external-content + vec0 sidecars. Typed front-end: search.For[T](db).Vector/FullText/Hybrid(...).
  • At-rest encryption — dedicated guide, example, and skill for sqlite.OpenEncrypted (pure-Go Adiantum cipher, no CGo); surfaced in README + comparison table.
  • Opt-in plural table namesorm.UsePluralTableNames(true) + RegisterPlural, via a dependency-free inflector shared by orm and query.
  • WhereRegex — index-friendly regex filter (GLOB prefix + REGEXP fallback).

Some breaking changes

  • orm.Op[T]orm.Event[T]
  • Typed search funcs KNN/Match/Fusesearch.For[T](db) builder (.Vector/.FullText/.Hybrid)
  • search.Load/LoadScoredFetch/FetchScored
  • orm.SearchKind dropped; orm.SearchIndex.Kind now uses dialect.SearchKind
  • Queryer interface removed

UsePluralTableNames + RegisterPlural: when enabled, the default (no-TableName) table name is pluralized snake_case (User -> users, Category -> categories), matching gorm. Off by default; an explicit TableName() always wins. A dependency-free inflector lives in internal/scan, and the toggle routes through scan.TableNameOf so the query and orm front-ends agree.
sqlite.WhereRegex(column, pattern) returns a WHERE fragment that pairs a GLOB prefix with REGEXP for anchored patterns (index range scan + residual filter), falling back to a plain REGEXP for unanchored ones. Requires the gosqlite regexp extension to be registered.
Declare search indexes on a model (a SearchIndexes() method or vec:/fts: tags); AutoMigrate provisions the FTS5/vec0 sidecars and keeps them current via SQL triggers (all writes) or ORM hooks (sidecar-only embeddings). Search through search.For[T](db).Vector/FullText/Hybrid, returning models in ranked order — int64 and string keys for vectors, int64-only for full-text. Adds the dialect SearchProvisioner/SearchRowSyncer capabilities over a neutral SearchSpec, the sqlite DDL + trigger/row-sync generation, and the typed searcher.

Folds in the cleanup entangled in the same files: the hook handle Op -> Event, removal of the unused Queryer interface, a single SearchKind enum (dialect.SearchKind), Load -> Fetch on the search read path, and inlining of one-line stdlib wrappers.
@arthurpro arthurpro requested a review from ditalini June 18, 2026 16:24
Add a dedicated encryption example (open with a key, ciphertext on disk,
reopen, reject the wrong key), guide, and skill, and surface encryption
in the README, docs index, and skills index — moving it out of the
search docs where it had been mis-bundled.

examples/encryption is registered in go.work.
@arthurpro arthurpro force-pushed the feat/search-naming branch from 0a40bb9 to d84e85f Compare June 18, 2026 16:35
@arthurpro arthurpro merged commit f84ddaf into main Jun 18, 2026
10 checks passed
@arthurpro arthurpro deleted the feat/search-naming branch June 18, 2026 17:41
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