Commit graph

51 commits

Author SHA1 Message Date
Deluan
fffbfc5f08 feat(db): statically compile spellfix1 SQLite extension
Vendor the spellfix1 extension source and compile it directly into the
binary via cgo, avoiding runtime shared library dependencies across
platforms. The extension is registered via sqlite3_auto_extension so
every new SQLite connection has spellfix1 available.

Signed-off-by: Deluan <deluan@navidrome.org>
2026-02-23 15:51:10 -05:00
Deluan Quintão
54de0dbc52
feat(server): implement FTS5-based full-text search (#5079)
* build: add sqlite_fts5 build tag to enable FTS5 support

* feat: add SearchBackend config option (default: fts)

* feat: add buildFTS5Query for safe FTS5 query preprocessing

* feat: add FTS5 search backend with config toggle, refactor legacy search

- Add searchExprFunc type and getSearchExpr() for backend selection
- Rename fullTextExpr to legacySearchExpr
- Add ftsSearchExpr using FTS5 MATCH subquery
- Update fullTextFilter in sql_restful.go to use configured backend

* feat: add FTS5 migration with virtual tables, triggers, and search_participants

Creates FTS5 virtual tables for media_file, album, and artist with
unicode61 tokenizer and diacritic folding. Adds search_participants
column, populates from JSON, and sets up INSERT/UPDATE/DELETE triggers.

* feat: populate search_participants in PostMapArgs for FTS5 indexing

* test: add FTS5 search integration tests

* fix: exclude FTS5 virtual tables from e2e DB restore

The restoreDB function iterates all tables in sqlite_master and
runs DELETE + INSERT to reset state. FTS5 contentless virtual tables
cannot be directly deleted from. Since triggers handle FTS5 sync
automatically, simply skip tables matching *_fts and *_fts_* patterns.

* build: add compile-time guard for sqlite_fts5 build tag

Same pattern as netgo: compilation fails with a clear error if
the sqlite_fts5 build tag is missing.

* build: add sqlite_fts5 tag to reflex dev server config

* build: extract GO_BUILD_TAGS variable in Makefile to avoid duplication

* fix: strip leading * from FTS5 queries to prevent "unknown special query" error

* feat: auto-append prefix wildcard to FTS5 search tokens for broader matching

Every plain search token now gets a trailing * appended (e.g., "love" becomes
"love*"), so searching for "love" also matches "lovelace", "lovely", etc.
Quoted phrases are preserved as exact matches without wildcards. Results are
ordered alphabetically by name/title, so shorter exact matches naturally
appear first.

* fix: clarify comments about FTS5 operator neutralization

The comments said "strip" but the code lowercases operators to
neutralize them (FTS5 operators are case-sensitive). Updated comments
to accurately describe the behavior.

* fix: use fmt.Sprintf for FTS5 phrase placeholders

The previous encoding used rune('0'+index) which silently breaks with
10+ quoted phrases. Use fmt.Sprintf for arbitrary index support.

* fix: validate and normalize SearchBackend config option

Normalize the value to lowercase and fall back to "fts" with a log
warning for unrecognized values. This prevents silent misconfiguration
from typos like "FTS", "Legacy", or "fts5".

* refactor: improve documentation for build tags and FTS5 requirements

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor: convert FTS5 query and search backend normalization tests to DescribeTable format

Signed-off-by: Deluan <deluan@navidrome.org>

* fix: add sqlite_fts5 build tag to golangci configuration

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: add UISearchDebounceMs configuration option and update related components

Signed-off-by: Deluan <deluan@navidrome.org>

* fix: fall back to legacy search when SearchFullString is enabled

FTS5 is token-based and cannot match substrings within words, so
getSearchExpr now returns legacySearchExpr when SearchFullString
is true, regardless of SearchBackend setting.

* fix: add sqlite_fts5 build tag to CI pipeline and Dockerfile

* fix: add WHEN clauses to FTS5 AFTER UPDATE triggers

Added WHEN clauses to the media_file_fts_au, album_fts_au, and
artist_fts_au triggers so they only fire when FTS-indexed columns
actually change. Previously, every row update (e.g., play count, rating,
starred status) triggered an unnecessary delete+insert cycle in the FTS
shadow tables. The WHEN clauses use IS NOT for NULL-safe comparison of
each indexed column, avoiding FTS index churn for non-indexed updates.

* feat: add SearchBackend configuration option to data and insights components

Signed-off-by: Deluan <deluan@navidrome.org>

* fix: enhance input sanitization for FTS5 by stripping additional punctuation and special characters

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: add search_normalized column for punctuated name search (R.E.M., AC/DC)

Add index-time normalization and query-time single-letter collapsing to
fix FTS5 search for punctuated names. A new search_normalized column
stores concatenated forms of punctuated words (e.g., "R.E.M." → "REM",
"AC/DC" → "ACDC") and is indexed in FTS5 tables. At query time, runs of
consecutive single letters (from dot-stripping) are collapsed into OR
expressions like ("R E M" OR REM*) to match both the original tokens and
the normalized form. This enables searching by "R.E.M.", "REM", "AC/DC",
"ACDC", "A-ha", or "Aha" and finding the correct results.

* refactor: simplify isSingleUnicodeLetter to avoid []rune allocation

Use utf8.DecodeRuneInString to check for a single Unicode letter
instead of converting the entire string to a []rune slice.

* feat: define ftsSearchColumns for flexible FTS5 search column inclusion

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: update collapseSingleLetterRuns to return quoted phrases for abbreviations

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: implement extractPunctuatedWords to handle artist/album names with embedded punctuation

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: implement extractPunctuatedWords to handle artist/album names with embedded punctuation

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor: punctuated word handling to improve processing of artist/album names

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: add CJK support for search queries with LIKE filters

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: enhance FTS5 search by adding album version support and CJK handling

Signed-off-by: Deluan <deluan@navidrome.org>

* refactor: search configuration to use structured options

Signed-off-by: Deluan <deluan@navidrome.org>

* feat: enhance search functionality to support punctuation-only queries and update related tests

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-02-21 17:52:42 -05:00
Deluan Quintão
69e2a6d620
build(netgo): make sure the project is always compiled with netgo build tag (#3428)
* build(netgo): make sure the project is always compiled with `netgo` build tag

* docs(netgo): better comments
2024-10-26 13:28:23 -04:00
Deluan
c380139606 Fix lint 2023-03-15 13:10:14 -04:00
Deluan
63fbccf5a9 Enable memory profiling 2023-03-15 12:43:25 -04:00
Deluan
10cd3152ba Remove misplaced import 2022-11-27 22:01:07 -05:00
Deluan
950b5dc1ce Remove math/rand and only use crypto/rand 2022-11-27 21:53:13 -05:00
Deluan
3972616585 New Criteria API 2021-10-23 20:25:28 -04:00
Yash Jipkate
af210c8903
Add Native Sharing REST API (#1150)
* Initial draft - UNTESTED

* changes to Save() and Update()

* apply col filter and limit nanoid

* remove columns to not update
2021-06-08 15:44:30 -04:00
Deluan
6ee45a9ccc Move project to Navidrome GitHub organization 2021-02-06 21:46:35 -05:00
Deluan
58a52c31c2 Turn off memory profiling, saving a couple of megabytes 2021-02-01 16:30:06 -05:00
Deluan
5021c0fd0c Replace multiconfig with cobra+viper 2020-07-02 17:53:51 -04:00
Deluan
75cd21da1f Add BaseURL configuration (fixes #103) 2020-04-03 19:05:38 -04:00
Deluan
15606770ca chore: removed non-working config flag 2020-03-22 01:13:55 -04:00
Deluan
a6b0c57ce0 feat: add a proper caching system to the transcoding functionality 2020-02-20 19:25:39 -05:00
Deluan
d1f8d39866 refactor: move banner to consts, closer to version 2020-02-04 10:14:53 -05:00
Deluan
7e65bb8f20 refactor: better integration between db and persistence packages
Will address support for different DBs in the future (+1 squashed commit)
Squashed commits:
[a014757] refactor: better integration between `db` and `persistence` packages
2020-02-01 17:23:03 -05:00
Deluan
71c1844bca refactor: new persistence, more SQL, less ORM 2020-02-01 17:23:03 -05:00
Deluan
828dc8f0f4 feat: add -help, simplified config loading 2020-01-26 16:21:07 -05:00
Deluan
8756f55650 Add git info to version 2020-01-25 11:06:04 -05:00
Deluan
5b84188f58 Add banner.txt as a static file 2020-01-24 23:45:31 -05:00
Deluan
bff6f3a4bd Rename env vars prefix to ND_ 2020-01-24 01:29:31 -05:00
Deluan
bee55c04c8 Rename project to Navidrome 2020-01-23 19:44:08 -05:00
Deluan
28cd3ec3e4 Fix startup order, setting LogLevel 2020-01-20 17:35:04 -05:00
Deluan
3a03284c59 Add routing for basic web ui 2020-01-19 19:35:03 -05:00
Deluan
c995766c45 Add startup banner 2020-01-13 18:24:54 -05:00
Deluan
536244bc44 Removed LedisDB persistence layer. May reimplement in the future (not likely thou) 2020-01-13 16:37:24 -05:00
Deluan
4b1c909a4d Make persistence provider pluggable at runtime 2020-01-11 15:27:32 -05:00
Deluan
48b465f2fb Simplify API routes mounting 2020-01-11 15:27:32 -05:00
Deluan
408030eb6c Refactor App to use DI 2020-01-11 15:27:32 -05:00
Deluan
30ebbc1fa1 Move API dependency injection to main package, opening the possibility to switch persistence without code changes 2020-01-11 15:27:32 -05:00
Deluan
23e38ec82f Removed (almost) all remaining init() 2020-01-09 22:44:45 -05:00
Deluan
5d2a7b1db1 Removed MainController 2020-01-09 22:44:45 -05:00
Deluan
e8a8313b43 Removed inject lib, only use wire for DI 2020-01-09 22:44:45 -05:00
Deluan
3af9972b41 Remove Beego tasks, make Importer available through DI 2020-01-09 22:44:45 -05:00
Deluan
79701caca3 Removed Beego routing/controllers, converted to Chi.
Also introduced Wire for dependency injection
2020-01-09 22:44:45 -05:00
Deluan
c417a00e62 Renamed project to CloudSonic 2017-04-01 09:47:14 -04:00
Deluan
09f98508a4 Removed duplicated import 2016-11-09 09:49:06 -05:00
Deluan
c2b1f9782b New configuration system 2016-03-30 00:05:57 -04:00
Deluan
9049d97820 Moving code away from conf package.
This is necessary, as the conf package will hold only configuration, and cannot have dependencies on other packages
2016-03-29 18:27:14 -04:00
Deluan
cad65f517c Polishing 2016-03-15 13:17:51 -04:00
Deluan
4b09eeccc2 Configuring "prod" 2016-03-11 21:14:32 -05:00
Deluan
12b0350d3e Task for continuously check for iTunes Library updates 2016-03-11 18:37:37 -05:00
Deluan
46e7627fd3 Optimized import, only updating changed data and purging old data 2016-03-08 14:19:07 -05:00
Deluan
4843ccb46c go fmt 2016-03-02 13:18:39 -05:00
Deluan
02a5fec6b6 Show Query params for invalid URL's 2016-03-01 20:42:20 -05:00
Deluan
4efb8ab031 Moved router to conf package 2016-03-01 09:23:40 -05:00
Deluan
375fd30045 Fixed AlbumId generation. Some code cleanup 2016-03-01 09:17:28 -05:00
Deluan
a25c09111b Removed doc code. For the API documentation see Subsonic site 2016-02-24 19:22:01 -05:00
Deluan
9a55fa1c64 Experiments with bleve, repositories and parsing itunes 2016-02-24 15:30:28 -05:00