🏑 index : ironmagma/quintodrome.git

package persistence

import (
	"github.com/navidrome/navidrome/conf"
	"github.com/navidrome/navidrome/conf/configtest"
	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

var _ = Describe("sqlRepository", func() {
	Describe("formatFullText", func() {
		It("prefixes with a space", func() {
			Expect(formatFullText("legiao urbana")).To(Equal(" legiao urbana"))
		})
	})

	Describe("getSearchStrategy", func() {
		It("returns FTS strategy by default", func() {
			DeferCleanup(configtest.SetupConfig())
			conf.Server.Search.Backend = "fts"
			conf.Server.Search.FullString = false

			strategy := getSearchStrategy("media_file", "test")
			Expect(strategy).ToNot(BeNil())
			sql, _, err := strategy.ToSql()
			Expect(err).ToNot(HaveOccurred())
			Expect(sql).To(ContainSubstring("MATCH"))
		})

		It("returns legacy LIKE strategy when SearchBackend is legacy", func() {
			DeferCleanup(configtest.SetupConfig())
			conf.Server.Search.Backend = "legacy"
			conf.Server.Search.FullString = false

			strategy := getSearchStrategy("media_file", "test")
			Expect(strategy).ToNot(BeNil())
			sql, _, err := strategy.ToSql()
			Expect(err).ToNot(HaveOccurred())
			Expect(sql).To(ContainSubstring("LIKE"))
		})

		It("falls back to legacy LIKE strategy when SearchFullString is enabled", func() {
			DeferCleanup(configtest.SetupConfig())
			conf.Server.Search.Backend = "fts"
			conf.Server.Search.FullString = true

			strategy := getSearchStrategy("media_file", "test")
			Expect(strategy).ToNot(BeNil())
			sql, _, err := strategy.ToSql()
			Expect(err).ToNot(HaveOccurred())
			Expect(sql).To(ContainSubstring("LIKE"))
		})

		It("routes CJK queries to LIKE strategy instead of FTS", func() {
			DeferCleanup(configtest.SetupConfig())
			conf.Server.Search.Backend = "fts"
			conf.Server.Search.FullString = false

			strategy := getSearchStrategy("media_file", "周杰伦")
			Expect(strategy).ToNot(BeNil())
			sql, _, err := strategy.ToSql()
			Expect(err).ToNot(HaveOccurred())
			// CJK should use LIKE, not MATCH
			Expect(sql).To(ContainSubstring("LIKE"))
			Expect(sql).NotTo(ContainSubstring("MATCH"))
		})

		It("routes non-CJK queries to FTS strategy", func() {
			DeferCleanup(configtest.SetupConfig())
			conf.Server.Search.Backend = "fts"
			conf.Server.Search.FullString = false

			strategy := getSearchStrategy("media_file", "beatles")
			Expect(strategy).ToNot(BeNil())
			sql, _, err := strategy.ToSql()
			Expect(err).ToNot(HaveOccurred())
			Expect(sql).To(ContainSubstring("MATCH"))
		})

		It("returns non-nil for single-character query (no min-length in strategy)", func() {
			DeferCleanup(configtest.SetupConfig())
			conf.Server.Search.Backend = "fts"
			conf.Server.Search.FullString = false

			strategy := getSearchStrategy("media_file", "a")
			Expect(strategy).ToNot(BeNil(), "single-char queries must be accepted by strategies (min-length is enforced in doSearch)")
		})

		It("returns non-nil for single-character query with legacy backend", func() {
			DeferCleanup(configtest.SetupConfig())
			conf.Server.Search.Backend = "legacy"
			conf.Server.Search.FullString = false

			strategy := getSearchStrategy("media_file", "a")
			Expect(strategy).ToNot(BeNil(), "single-char queries must be accepted by legacy strategy (min-length is enforced in doSearch)")
		})

		It("uses legacy for CJK when SearchBackend is legacy", func() {
			DeferCleanup(configtest.SetupConfig())
			conf.Server.Search.Backend = "legacy"
			conf.Server.Search.FullString = false

			strategy := getSearchStrategy("media_file", "周杰伦")
			Expect(strategy).ToNot(BeNil())
			sql, _, err := strategy.ToSql()
			Expect(err).ToNot(HaveOccurred())
			// Legacy should still use full_text column LIKE
			Expect(sql).To(ContainSubstring("LIKE"))
			Expect(sql).To(ContainSubstring("full_text"))
		})
	})
})