internal/store/fts.go
27 lines · 1020 bytes
1 symbol in this file
1package store
2
3import "strings"
4
5// FTSQuery turns what someone typed into an FTS5 MATCH expression.
6//
7// FTS5's query language is not free text: bare `-`, `*`, `:`, `(`, `NOT`
8// and an odd number of quotes are all syntax, and a syntax error surfaces
9// as a failed query rather than no results. Nobody searching for "c++" or
10// "foo: bar" means any of that. Every whitespace-separated run becomes a
11// quoted phrase, which FTS5 treats as a literal and joins with an
12// implicit AND, so the result is "rows containing all of these words".
13func FTSQuery(q string) string {
14 var terms []string
15 for _, f := range strings.Fields(q) {
16 // A double quote inside a phrase is escaped by doubling it.
17 f = strings.ReplaceAll(f, `"`, `""`)
18 terms = append(terms, `"`+f+`"`)
19 }
20 if len(terms) == 0 {
21 // Matches nothing, rather than being a syntax error. A caller
22 // should not run a search for an empty query, but if one does the
23 // answer is no rows, not a failure.
24 return `""`
25 }
26 return strings.Join(terms, " ")
27}