From 6886de04d4215ea45ae535b64a604a79292bff77 Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Tue, 31 Oct 2017 11:52:10 -0400 Subject: PLT-6071/PLT-8004 Fixed not being able to autocomplete 'Town Square' (#7746) --- store/sqlstore/channel_store.go | 2 +- store/sqlstore/user_store.go | 53 ++++++++++++++++++++-------------------- store/storetest/channel_store.go | 20 +++++++++++++++ 3 files changed, 48 insertions(+), 27 deletions(-) (limited to 'store') diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go index cf712d974..2654082c8 100644 --- a/store/sqlstore/channel_store.go +++ b/store/sqlstore/channel_store.go @@ -1263,7 +1263,7 @@ func (s SqlChannelStore) performSearch(searchQuery string, term string, paramete searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1) } else { isPostgreSQL := s.DriverName() == model.DATABASE_DRIVER_POSTGRES - searchQuery = generateSearchQuery(searchQuery, term, "Name, DisplayName", parameters, isPostgreSQL) + searchQuery = generateSearchQuery(searchQuery, []string{term}, []string{"Name", "DisplayName"}, parameters, isPostgreSQL) } var channels model.ChannelList diff --git a/store/sqlstore/user_store.go b/store/sqlstore/user_store.go index 3fafc7eab..09b1ce1be 100644 --- a/store/sqlstore/user_store.go +++ b/store/sqlstore/user_store.go @@ -17,14 +17,17 @@ import ( ) const ( - PROFILES_IN_CHANNEL_CACHE_SIZE = model.CHANNEL_CACHE_SIZE - PROFILES_IN_CHANNEL_CACHE_SEC = 900 // 15 mins - PROFILE_BY_IDS_CACHE_SIZE = model.SESSION_CACHE_SIZE - PROFILE_BY_IDS_CACHE_SEC = 900 // 15 mins - USER_SEARCH_TYPE_NAMES_NO_FULL_NAME = "Username, Nickname" - USER_SEARCH_TYPE_NAMES = "Username, FirstName, LastName, Nickname" - USER_SEARCH_TYPE_ALL_NO_FULL_NAME = "Username, Nickname, Email" - USER_SEARCH_TYPE_ALL = "Username, FirstName, LastName, Nickname, Email" + PROFILES_IN_CHANNEL_CACHE_SIZE = model.CHANNEL_CACHE_SIZE + PROFILES_IN_CHANNEL_CACHE_SEC = 900 // 15 mins + PROFILE_BY_IDS_CACHE_SIZE = model.SESSION_CACHE_SIZE + PROFILE_BY_IDS_CACHE_SEC = 900 // 15 mins +) + +var ( + USER_SEARCH_TYPE_NAMES_NO_FULL_NAME = []string{"Username", "Nickname"} + USER_SEARCH_TYPE_NAMES = []string{"Username", "FirstName", "LastName", "Nickname"} + USER_SEARCH_TYPE_ALL_NO_FULL_NAME = []string{"Username", "Nickname", "Email"} + USER_SEARCH_TYPE_ALL = []string{"Username", "FirstName", "LastName", "Nickname", "Email"} ) type SqlUserStore struct { @@ -86,10 +89,10 @@ func (us SqlUserStore) CreateIndexesIfNotExists() { us.CreateIndexIfNotExists("idx_users_lastname_lower", "Users", "lower(LastName)") } - us.CreateFullTextIndexIfNotExists("idx_users_all_txt", "Users", USER_SEARCH_TYPE_ALL) - us.CreateFullTextIndexIfNotExists("idx_users_all_no_full_name_txt", "Users", USER_SEARCH_TYPE_ALL_NO_FULL_NAME) - us.CreateFullTextIndexIfNotExists("idx_users_names_txt", "Users", USER_SEARCH_TYPE_NAMES) - us.CreateFullTextIndexIfNotExists("idx_users_names_no_full_name_txt", "Users", USER_SEARCH_TYPE_NAMES_NO_FULL_NAME) + us.CreateFullTextIndexIfNotExists("idx_users_all_txt", "Users", strings.Join(USER_SEARCH_TYPE_ALL, ", ")) + us.CreateFullTextIndexIfNotExists("idx_users_all_no_full_name_txt", "Users", strings.Join(USER_SEARCH_TYPE_ALL_NO_FULL_NAME, ", ")) + us.CreateFullTextIndexIfNotExists("idx_users_names_txt", "Users", strings.Join(USER_SEARCH_TYPE_NAMES, ", ")) + us.CreateFullTextIndexIfNotExists("idx_users_names_no_full_name_txt", "Users", strings.Join(USER_SEARCH_TYPE_NAMES_NO_FULL_NAME, ", ")) } func (us SqlUserStore) Save(user *model.User) store.StoreChannel { @@ -1028,25 +1031,22 @@ var ignoreUserSearchChar = []string{ "*", } -func generateSearchQuery(searchQuery, term, searchField string, parameters map[string]interface{}, isPostgreSQL bool) string { - splitTerms := strings.Fields(term) - splitFields := strings.Split(searchField, ", ") - - terms := []string{} - for i, term := range splitTerms { - fields := []string{} - for _, field := range splitFields { +func generateSearchQuery(searchQuery string, terms []string, fields []string, parameters map[string]interface{}, isPostgreSQL bool) string { + searchTerms := []string{} + for i, term := range terms { + searchFields := []string{} + for _, field := range fields { if isPostgreSQL { - fields = append(fields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*' ", field, fmt.Sprintf(":Term%d", i))) + searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*' ", field, fmt.Sprintf(":Term%d", i))) } else { - fields = append(fields, fmt.Sprintf("%s LIKE %s escape '*' ", field, fmt.Sprintf(":Term%d", i))) + searchFields = append(searchFields, fmt.Sprintf("%s LIKE %s escape '*' ", field, fmt.Sprintf(":Term%d", i))) } } - terms = append(terms, fmt.Sprintf("(%s)", strings.Join(fields, " OR "))) + searchTerms = append(searchTerms, fmt.Sprintf("(%s)", strings.Join(searchFields, " OR "))) parameters[fmt.Sprintf("Term%d", i)] = fmt.Sprintf("%s%%", term) } - searchClause := strings.Join(terms, " AND ") + searchClause := strings.Join(searchTerms, " AND ") return strings.Replace(searchQuery, "SEARCH_CLAUSE", fmt.Sprintf(" AND %s ", searchClause), 1) } @@ -1082,13 +1082,14 @@ func (us SqlUserStore) performSearch(searchQuery string, term string, options ma searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1) } else { isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES - searchQuery = generateSearchQuery(searchQuery, term, searchType, parameters, isPostgreSQL) + searchQuery = generateSearchQuery(searchQuery, strings.Fields(term), searchType, parameters, isPostgreSQL) } var users []*model.User if _, err := us.GetReplica().Select(&users, searchQuery, parameters); err != nil { - result.Err = model.NewAppError("SqlUserStore.Search", "store.sql_user.search.app_error", nil, "term="+term+", "+"search_type="+searchType+", "+err.Error(), http.StatusInternalServerError) + result.Err = model.NewAppError("SqlUserStore.Search", "store.sql_user.search.app_error", nil, + fmt.Sprintf("term=%v, search_type=%v, %v", term, searchType, err.Error()), http.StatusInternalServerError) } else { for _, u := range users { u.Sanitize(map[string]bool{}) diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go index cb4e8fa26..1189fd976 100644 --- a/store/storetest/channel_store.go +++ b/store/storetest/channel_store.go @@ -1861,6 +1861,13 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { o8.Type = model.CHANNEL_PRIVATE store.Must(ss.Channel().Save(&o8, -1)) + o9 := model.Channel{} + o9.TeamId = o1.TeamId + o9.DisplayName = "Town Square" + o9.Name = "town-square" + o9.Type = model.CHANNEL_OPEN + store.Must(ss.Channel().Save(&o9, -1)) + if result := <-ss.Channel().SearchInTeam(o1.TeamId, "ChannelA"); result.Err != nil { t.Fatal(result.Err) } else { @@ -1926,6 +1933,19 @@ func testChannelStoreSearchInTeam(t *testing.T, ss store.Store) { t.Fatal("should be empty") } } + + if result := <-ss.Channel().SearchInTeam(o1.TeamId, "town square"); result.Err != nil { + t.Fatal(result.Err) + } else { + channels := result.Data.(*model.ChannelList) + if len(*channels) != 1 { + t.Fatal("should return 1 channel") + } + + if (*channels)[0].Name != o9.Name { + t.Fatal("wrong channel returned") + } + } } func testChannelStoreGetMembersByIds(t *testing.T, ss store.Store) { -- cgit v1.2.3-1-g7c22