fix(subsonic): handle empty quoted phrases in FTS5 query and search expression
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
@@ -134,7 +134,7 @@ func isDottedAbbreviation(w string, subTokens []string) bool {
|
||||
// special characters to prevent query injection.
|
||||
func buildFTS5Query(userInput string) string {
|
||||
q := strings.TrimSpace(userInput)
|
||||
if q == "" {
|
||||
if q == "" || q == `""` {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ var ftsSearchColumns = map[string]string{
|
||||
func ftsSearchExpr(tableName string, s string) Sqlizer {
|
||||
q := buildFTS5Query(s)
|
||||
if q == "" {
|
||||
s = strings.TrimSpace(s)
|
||||
s = strings.TrimSpace(strings.ReplaceAll(s, `"`, ""))
|
||||
if s != "" {
|
||||
log.Trace("Search using LIKE fallback for non-tokenizable query", "table", tableName, "query", s)
|
||||
return likeSearchExpr(tableName, s)
|
||||
|
||||
@@ -49,6 +49,7 @@ var _ = DescribeTable("buildFTS5Query",
|
||||
Entry("preserves quoted abbreviation verbatim", `"R.E.M."`, `"R.E.M."`),
|
||||
Entry("returns empty string for punctuation-only input", "!!!!!!!", ""),
|
||||
Entry("returns empty string for mixed punctuation", "!@#$%^&", ""),
|
||||
Entry("returns empty string for empty quoted phrase", `""`, ""),
|
||||
)
|
||||
|
||||
var _ = DescribeTable("normalizeForFTS",
|
||||
@@ -204,6 +205,10 @@ var _ = Describe("ftsSearchExpr", func() {
|
||||
Expect(ftsSearchExpr("media_file", "")).To(BeNil())
|
||||
Expect(ftsSearchExpr("media_file", " ")).To(BeNil())
|
||||
})
|
||||
|
||||
It("returns nil for empty quoted phrase", func() {
|
||||
Expect(ftsSearchExpr("media_file", `""`)).To(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("FTS5 Integration Search", func() {
|
||||
|
||||
@@ -107,6 +107,16 @@ var _ = Describe("Search Endpoints", func() {
|
||||
Expect(resp.SearchResult3.Artist[0].Id).ToNot(BeEmpty())
|
||||
})
|
||||
|
||||
It("returns all results when query is empty (OpenSubsonic)", func() {
|
||||
resp := doReq("search3", "query", "")
|
||||
|
||||
Expect(resp.Status).To(Equal(responses.StatusOK))
|
||||
Expect(resp.SearchResult3).ToNot(BeNil())
|
||||
Expect(resp.SearchResult3.Artist).To(HaveLen(4))
|
||||
Expect(resp.SearchResult3.Album).To(HaveLen(5))
|
||||
Expect(resp.SearchResult3.Song).To(HaveLen(6))
|
||||
})
|
||||
|
||||
It("finds across all entity types simultaneously", func() {
|
||||
// "Beatles" should match artist, albums, and songs by The Beatles
|
||||
resp := doReq("search3", "query", "Beatles")
|
||||
|
||||
Reference in New Issue
Block a user