diff --git a/store/sqlstore/user_store.go b/store/sqlstore/user_store.go index f080872ab7..6583971640 100644 --- a/store/sqlstore/user_store.go +++ b/store/sqlstore/user_store.go @@ -1502,10 +1502,21 @@ func generateSearchQuery(query sq.SelectBuilder, terms []string, fields []string termArgs := []any{} var dbSpecificTerm string + if isPostgreSQL { + // Escaping the : in case of a Postgres search. + term = strings.ReplaceAll(term, ":", "\\:") + } + for _, field := range fields { if isPostgreSQL { - searchFields = append(searchFields, fmt.Sprintf("to_tsvector(lower(%[1]s)) @@ to_tsquery(concat(lower(?),':*'))", field)) - dbSpecificTerm = strings.TrimLeft(term, "@") + if strings.TrimLeft(term, "@") == "" { + // For wildcard search, we need to fall back to pattern matching. + searchFields = append(searchFields, fmt.Sprintf("%s ILIKE ? escape '*' ", field)) + dbSpecificTerm = fmt.Sprintf("%s%%", strings.TrimLeft(term, "@")) + } else { + searchFields = append(searchFields, fmt.Sprintf("to_tsvector(lower(%[1]s)) @@ to_tsquery(concat(lower(?),':*'))", field)) + dbSpecificTerm = strings.TrimLeft(term, "@") + } } else { searchFields = append(searchFields, fmt.Sprintf("%s LIKE ? escape '*' ", field)) dbSpecificTerm = fmt.Sprintf("%s%%", strings.TrimLeft(term, "@")) diff --git a/store/storetest/user_store.go b/store/storetest/user_store.go index 84dba22cb4..14cde98222 100644 --- a/store/storetest/user_store.go +++ b/store/storetest/user_store.go @@ -2800,6 +2800,22 @@ func testUserStoreSearch(t *testing.T, ss store.Store) { }, []*model.User{u3}, }, + { + "escape :", + t1id, + "ji:m", + &model.UserSearchOptions{}, + []*model.User{}, + }, + { + "wildcard search", + t1id, + "@", + &model.UserSearchOptions{ + Limit: model.UserSearchDefaultLimit, + }, + []*model.User{u2, u1, u3}, + }, } for _, testCase := range testCases {