From ec0eba4befa8cbcd6209b128e5678a97d47ff56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Tue, 3 Feb 2026 18:09:32 +0100 Subject: [PATCH] fix: escape FTS5 queries to handle special characters Wrap search queries in double quotes for FTS5 literal matching. This prevents dots, colons, and other special characters from being interpreted as FTS5 operators. Fixes: "fts5: syntax error near '.'" when searching for option paths like "services.nginx". Co-Authored-By: Claude Opus 4.5 --- internal/database/sqlite.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/database/sqlite.go b/internal/database/sqlite.go index 1591640..1e0e241 100644 --- a/internal/database/sqlite.go +++ b/internal/database/sqlite.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "fmt" + "strings" _ "modernc.org/sqlite" ) @@ -323,7 +324,11 @@ func (s *SQLiteStore) SearchOptions(ctx context.Context, revisionID int64, query WHERE o.revision_id = ? AND options_fts MATCH ?` - args := []interface{}{revisionID, query} + // Escape the query for FTS5 by wrapping in double quotes for literal matching. + // This prevents special characters (dots, colons, etc.) from being interpreted as operators. + // Also escape any double quotes within the query. + escapedQuery := `"` + strings.ReplaceAll(query, `"`, `""`) + `"` + args := []interface{}{revisionID, escapedQuery} if filters.Type != "" { baseQuery += " AND o.type = ?"