Generate DDL to create the full-text search index.
Run it with exec(), which runs a script of several statements. On
PostgreSQL the script holds DO blocks with semicolons inside them, so a
caller that splits it on ; itself would cut them.
Name for the FTS index/virtual table.
Columns to index.
OptionalcontentSource table (for external-content FTS5).
Optionaltokenizer?: stringTokenizer config (e.g. 'porter ascii').
Optionalweights?: Record<string, PostgreSQL: a weight per column (A highest, D lowest) for ranking. The SQLite engines rank without it.
A rank value, in each engine's own direction.
SQLite FTS5: memory_traces_fts.rank (lower is better)
SQLite FTS4: length(offsets(memory_traces_fts)) (higher is better)
Postgres: ts_rank(_tsv, websearch_to_tsquery('english', $1)) (higher is better)
Use relevanceOrder to order the same way on every engine.
OptionalqueryPlaceholder: stringAn ORDER BY fragment that puts the best match first on every engine.
SQLite FTS5: memory_traces_fts.rank
SQLite FTS4: length(offsets(memory_traces_fts)) DESC
Postgres: ts_rank(_tsv, websearch_to_tsquery('english', $1)) DESC
OptionalqueryPlaceholder: stringGenerate an INSERT to sync external-content FTS after a row insert.
SQLite: INSERT INTO fts_table (rowid, col1, col2) VALUES (expr, ?, ?)
Postgres: UPDATE content_table SET _tsv = to_tsvector(...) WHERE ...
Generate a SELECT joining the FTS index to the content table. This handles the structural difference between FTS5 (separate virtual table joined via rowid) and Postgres (tsvector column on the content table itself).
The base table (e.g. 'memory_traces').
Alias for the content table (e.g. 't').
Alias for the FTS table/column (e.g. 'fts').
FTS index/virtual table name.
FROM/JOIN clause fragment.
Full-text search abstraction.
better-sqlite3 uses FTS5 virtual tables; sql.js and IndexedDB use FTS4, which their stock sql.js build has (it has no FTS5). Postgres implementations use tsvector columns with GIN indexes. Methods return SQL strings — no database calls.