internal/store/fts.go

d775997ead04022093817ab513287b5886065247
gitbay/internal/store/fts.go history · blame · raw

27 lines · 1020 bytes

 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}