refactor(assistant): replace JSON LIKE handling with JSON contains logic
- Updated GetAssistants and DeleteAssistants methods to utilize jsonContainsValue for filtering tags and locales, improving query compatibility across database drivers. - Renamed related test functions to reflect the new JSON handling approach. - Removed deprecated jsonLikeExpr and whereJsonLike methods to streamline codebase.
This commit is contained in:
parent
4b30e80924
commit
8d44ef31c1
3 changed files with 32 additions and 41 deletions
|
|
@ -319,8 +319,12 @@ func (store *Xun) GetAssistants(filter types.AssistantFilter, locale ...string)
|
|||
if len(filter.Tags) > 0 {
|
||||
qb.Where(func(qb query.Query) {
|
||||
for i, tag := range filter.Tags {
|
||||
pattern := fmt.Sprintf("%%\"%s\"%%", tag)
|
||||
store.whereJsonLike(qb, "tags", pattern, i > 0)
|
||||
val := store.jsonContainsValue(fmt.Sprintf("%%\"%s\"%%", tag))
|
||||
if i == 0 {
|
||||
qb.WhereJSONContains("tags", val)
|
||||
} else {
|
||||
qb.OrWhereJSONContains("tags", val)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -332,7 +336,8 @@ func (store *Xun) GetAssistants(filter types.AssistantFilter, locale ...string)
|
|||
qb.Where("name", "like", kw).
|
||||
OrWhere("description", "like", kw).
|
||||
OrWhere("capabilities", "like", kw)
|
||||
store.whereJsonLike(qb, "locales", kw, true)
|
||||
localeVal := store.jsonContainsValue(kw)
|
||||
qb.OrWhereJSONContains("locales", localeVal)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -708,8 +713,12 @@ func (store *Xun) DeleteAssistants(filter types.AssistantFilter) (int64, error)
|
|||
if len(filter.Tags) > 0 {
|
||||
qb.Where(func(qb query.Query) {
|
||||
for i, tag := range filter.Tags {
|
||||
pattern := fmt.Sprintf("%%\"%s\"%%", tag)
|
||||
store.whereJsonLike(qb, "tags", pattern, i > 0)
|
||||
val := store.jsonContainsValue(fmt.Sprintf("%%\"%s\"%%", tag))
|
||||
if i == 0 {
|
||||
qb.WhereJSONContains("tags", val)
|
||||
} else {
|
||||
qb.OrWhereJSONContains("tags", val)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -900,6 +909,9 @@ func (store *Xun) translate(model *types.AssistantModel, assistantID string, loc
|
|||
|
||||
// sandboxRawSQL returns dialect-specific raw SQL fragments for sandbox JSON null detection.
|
||||
// Returns (notNullExpr, isNullExpr) for filtering sandbox field.
|
||||
// WhereRaw is used here because this is a JSON literal `null` comparison, not a JSON array
|
||||
// contains query. Each dialect requires different casting to compare the JSON value as text.
|
||||
// No bind parameters are needed (pure string comparison), so no placeholder issues.
|
||||
func (store *Xun) sandboxRawSQL() (string, string) {
|
||||
switch store.getDriver() {
|
||||
case "postgres":
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package xun
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
|
|
@ -198,33 +199,13 @@ func (store *Xun) getDriver() string {
|
|||
return "mysql"
|
||||
}
|
||||
|
||||
// jsonLikeExpr returns a dialect-specific SQL expression for LIKE on a JSON column.
|
||||
// PostgreSQL requires casting json/jsonb to text before applying LIKE.
|
||||
func (store *Xun) jsonLikeExpr(column string) string {
|
||||
switch store.getDriver() {
|
||||
case "postgres":
|
||||
return fmt.Sprintf(`"%s"::text LIKE ?`, column)
|
||||
default:
|
||||
return column + " LIKE ?"
|
||||
}
|
||||
}
|
||||
|
||||
// whereJsonLike applies a LIKE condition on a JSON column with proper dialect handling.
|
||||
func (store *Xun) whereJsonLike(qb query.Query, column, pattern string, or bool) {
|
||||
if store.getDriver() == "postgres" {
|
||||
expr := fmt.Sprintf(`"%s"::text LIKE ?`, column)
|
||||
if or {
|
||||
qb.OrWhereRaw(expr, pattern)
|
||||
} else {
|
||||
qb.WhereRaw(expr, pattern)
|
||||
}
|
||||
} else {
|
||||
if or {
|
||||
qb.OrWhere(column, "like", pattern)
|
||||
} else {
|
||||
qb.Where(column, "like", pattern)
|
||||
}
|
||||
// jsonContainsValue formats a value for WhereJSONContains.
|
||||
// PG/MySQL need JSON string (e.g. `"tag"`), SQLite needs LIKE pattern (e.g. `%"tag"%`).
|
||||
func (store *Xun) jsonContainsValue(value string) string {
|
||||
if store.getDriver() == "sqlite3" {
|
||||
return value
|
||||
}
|
||||
return strings.TrimSuffix(strings.TrimPrefix(value, "%"), "%")
|
||||
}
|
||||
|
||||
// GenerateAssistantID generates a random-looking 6-digit ID
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ func TestSandboxRawSQLAllDialects(t *testing.T) {
|
|||
assert.Contains(t, isNull, "=")
|
||||
}
|
||||
|
||||
func TestJsonLikeExpr(t *testing.T) {
|
||||
func TestJsonContainsValue(t *testing.T) {
|
||||
test.Prepare(t, config.Conf)
|
||||
defer test.Clean()
|
||||
|
||||
|
|
@ -89,22 +89,20 @@ func TestJsonLikeExpr(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
xunStore := store.(*Xun)
|
||||
|
||||
expr := xunStore.jsonLikeExpr("tags")
|
||||
assert.Contains(t, expr, "LIKE ?")
|
||||
|
||||
driver := xunStore.getDriver()
|
||||
val := xunStore.jsonContainsValue(`%"admin"%`)
|
||||
switch driver {
|
||||
case "postgres":
|
||||
assert.Contains(t, expr, `"tags"::text`)
|
||||
case "sqlite3":
|
||||
assert.Equal(t, `%"admin"%`, val, "SQLite keeps LIKE pattern as-is")
|
||||
default:
|
||||
assert.Equal(t, "tags LIKE ?", expr)
|
||||
assert.Equal(t, `"admin"`, val, "PG/MySQL strips % wrappers for JSON value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonLikeExprFallback(t *testing.T) {
|
||||
func TestJsonContainsValueFallback(t *testing.T) {
|
||||
store := &Xun{}
|
||||
expr := store.jsonLikeExpr("tags")
|
||||
assert.Equal(t, "tags LIKE ?", expr)
|
||||
val := store.jsonContainsValue(`%"test"%`)
|
||||
assert.Equal(t, `"test"`, val, "Default (mysql) strips % wrappers")
|
||||
}
|
||||
|
||||
func TestToDBTime(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue