diff --git a/store/sqlstore/user_store.go b/store/sqlstore/user_store.go index 201aac0ca3..331061792a 100644 --- a/store/sqlstore/user_store.go +++ b/store/sqlstore/user_store.go @@ -1509,34 +1509,17 @@ func generateSearchQuery(query sq.SelectBuilder, terms []string, fields []string for _, term := range terms { searchFields := []string{} termArgs := []any{} - var dbSpecificTerm string - - if isPostgreSQL { - // Refer to https://www.postgresql.org/docs/current/functions-textsearch.html for the list of operators. - for _, c := range []string{":", "(", ")", "<", "!", "|"} { - // Escaping the special chars in case of a Postgres search. - term = strings.ReplaceAll(term, c, "\\"+c) - } - } - for _, field := range fields { if isPostgreSQL { - 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, "@") - } + searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(?) escape '*' ", field)) } else { searchFields = append(searchFields, fmt.Sprintf("%s LIKE ? escape '*' ", field)) - dbSpecificTerm = fmt.Sprintf("%s%%", strings.TrimLeft(term, "@")) } - termArgs = append(termArgs, dbSpecificTerm) + termArgs = append(termArgs, fmt.Sprintf("%s%%", strings.TrimLeft(term, "@"))) } query = query.Where(fmt.Sprintf("(%s)", strings.Join(searchFields, " OR ")), termArgs...) } + return query } diff --git a/store/storetest/user_store.go b/store/storetest/user_store.go index 69841d3fdd..db7ca1db78 100644 --- a/store/storetest/user_store.go +++ b/store/storetest/user_store.go @@ -94,7 +94,6 @@ func TestUserStore(t *testing.T, ss store.Store, s SqlStore) { t.Run("ResetLastPictureUpdate", func(t *testing.T) { testUserStoreResetLastPictureUpdate(t, ss) }) t.Run("GetKnownUsers", func(t *testing.T) { testGetKnownUsers(t, ss) }) t.Run("GetUsersWithInvalidEmails", func(t *testing.T) { testGetUsersWithInvalidEmails(t, ss) }) - t.Run("SearchMultilingual", func(t *testing.T) { testUserStoreSearchUsersMultilingual(t, ss, s) }) } func testUserStoreSave(t *testing.T, ss store.Store) { @@ -2809,36 +2808,6 @@ func testUserStoreSearch(t *testing.T, ss store.Store) { }, []*model.User{u3}, }, - { - "escape :", - t1id, - "ji:m", - &model.UserSearchOptions{}, - []*model.User{}, - }, - { - "escape ( and )", - t1id, - "ji(bah)", - &model.UserSearchOptions{}, - []*model.User{}, - }, - { - "escape <", - t1id, - "ji(bah<", - &model.UserSearchOptions{}, - []*model.User{}, - }, - { - "wildcard search", - t1id, - "@", - &model.UserSearchOptions{ - Limit: model.UserSearchDefaultLimit, - }, - []*model.User{u2, u1, u3}, - }, } for _, testCase := range testCases { @@ -6050,174 +6019,3 @@ func testGetUsersWithInvalidEmails(t *testing.T, ss store.Store) { require.NoError(t, err) assert.Len(t, users, 1) } - -func testUserStoreSearchUsersMultilingual(t *testing.T, ss store.Store, s SqlStore) { - u1 := &model.User{ - Username: "test1" + model.NewId(), - FirstName: "Inígo", - LastName: "Martínez", - Nickname: "Berridi", - Email: MakeEmail(), - } - _, err := ss.User().Save(u1) - require.NoError(t, err) - defer func() { require.NoError(t, ss.User().PermanentDelete(u1.Id)) }() - - u2 := &model.User{ - Username: "test2" + model.NewId(), - FirstName: "Zinëdìne", - LastName: "Zidanë", - Email: MakeEmail(), - } - _, err = ss.User().Save(u2) - require.NoError(t, err) - defer func() { require.NoError(t, ss.User().PermanentDelete(u2.Id)) }() - - u3 := &model.User{ - Username: "test3" + model.NewId(), - FirstName: "Thomas ", - LastName: "Müller", - Nickname: "Fußballspieler", - Email: MakeEmail(), - } - _, err = ss.User().Save(u3) - require.NoError(t, err) - defer func() { require.NoError(t, ss.User().PermanentDelete(u3.Id)) }() - - u4 := &model.User{ - Username: "test4" + model.NewId(), - FirstName: "Jérémie ", - LastName: "Jéry", - Email: MakeEmail(), - } - _, err = ss.User().Save(u4) - require.NoError(t, err) - defer func() { require.NoError(t, ss.User().PermanentDelete(u4.Id)) }() - - // The users returned from the database will have AuthData as an empty string. - nilAuthData := new(string) - *nilAuthData = "" - u1.AuthData = nilAuthData - u2.AuthData = nilAuthData - u3.AuthData = nilAuthData - u4.AuthData = nilAuthData - - testCases := []struct { - Description string - Term string - Options *model.UserSearchOptions - ExpectedPostgres []*model.User - ExpectedMysql []*model.User - Language string - }{ - { - "search test1 player", - "inig", - &model.UserSearchOptions{ - AllowFullNames: true, - Limit: model.UserSearchDefaultLimit, - }, - []*model.User{u1}, - []*model.User{u1}, - "spanish", - }, - { - "search test2 player", - "zine", - &model.UserSearchOptions{ - AllowFullNames: true, - Limit: model.UserSearchDefaultLimit, - }, - []*model.User{u2}, - []*model.User{u2}, - "french", - }, - { - "search test2 player", - "zidane", - &model.UserSearchOptions{ - AllowFullNames: true, - Limit: model.UserSearchDefaultLimit, - }, - []*model.User{u2}, - []*model.User{u2}, - "french", - }, - { - "search test3 player", - "muller", - &model.UserSearchOptions{ - AllowFullNames: true, - Limit: model.UserSearchDefaultLimit, - }, - []*model.User{u3}, - []*model.User{u3}, - "german", - }, - { - "search test3 player", - "muller", - &model.UserSearchOptions{ - AllowFullNames: true, - Limit: model.UserSearchDefaultLimit, - }, - []*model.User{}, - []*model.User{u3}, - "english", - }, - { - "search test4 player", - "jere", - &model.UserSearchOptions{ - AllowFullNames: true, - Limit: model.UserSearchDefaultLimit, - }, - []*model.User{u4}, - []*model.User{u4}, - "spanish", - }, - { - "search test4 player", - "jere", - &model.UserSearchOptions{ - AllowFullNames: true, - Limit: model.UserSearchDefaultLimit, - }, - []*model.User{}, - []*model.User{u4}, - "english", - }, - } - - var initialDefaultTextSearchConfig string - if s.DriverName() == model.DatabaseDriverPostgres { - error := s.GetMasterX().Get(&initialDefaultTextSearchConfig, `SHOW default_text_search_config`) - require.NoError(t, error) - } - - for _, testCase := range testCases { - if s.DriverName() == model.DatabaseDriverPostgres { - _, error := s.GetMasterX().Exec("SET default_text_search_config TO '" + testCase.Language + "'") - require.NoError(t, error) - } - t.Run(testCase.Description, func(t *testing.T) { - users, err := ss.User().SearchWithoutTeam( - testCase.Term, - testCase.Options, - ) - - if s.DriverName() != model.DatabaseDriverPostgres { - require.NoError(t, err) - assertUsers(t, testCase.ExpectedMysql, users) - } else { - require.NoError(t, err) - assertUsers(t, testCase.ExpectedPostgres, users) - } - }) - } - - if s.DriverName() == model.DatabaseDriverPostgres { - _, error := s.GetMasterX().Exec("SET default_text_search_config TO '" + initialDefaultTextSearchConfig + "'") - require.NoError(t, error) - } -}