From 92db356484ad066120c23ca878f97d0b1e023578 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Wed, 21 May 2025 14:19:38 -0300 Subject: [PATCH] MM-62158: group store no select star, part3 (#30927) * migrate getGroupsAssociatedToChannelsByTeam * migrate GetGroups * migrate teamMembersMinusGroupMembersQuery * migrate channelMembersMinusGroupMembersQuery --- server/channels/store/sqlstore/group_store.go | 97 +++++++++---------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/server/channels/store/sqlstore/group_store.go b/server/channels/store/sqlstore/group_store.go index 38a08f1e3f..6273cd0fba 100644 --- a/server/channels/store/sqlstore/group_store.go +++ b/server/channels/store/sqlstore/group_store.go @@ -1340,9 +1340,8 @@ func (s *SqlGroupStore) groupsBySyncableBaseQuery(st model.GroupSyncableType, t } func (s *SqlGroupStore) getGroupsAssociatedToChannelsByTeam(teamID string, opts model.GroupSearchOpts) sq.SelectBuilder { - query := s.getQueryBuilder(). - Select("gc.ChannelId, UserGroups.*, gc.SchemeAdmin AS SyncableSchemeAdmin"). - From("UserGroups"). + query := s.userGroupsSelectQuery. + Columns("gc.ChannelId", "gc.SchemeAdmin AS SyncableSchemeAdmin"). LeftJoin(` (SELECT GroupChannels.GroupId, GroupChannels.ChannelId, GroupChannels.DeleteAt, GroupChannels.SchemeAdmin @@ -1358,9 +1357,8 @@ func (s *SqlGroupStore) getGroupsAssociatedToChannelsByTeam(teamID string, opts OrderBy("UserGroups.DisplayName") if opts.IncludeMemberCount { - query = s.getQueryBuilder(). - Select("gc.ChannelId, UserGroups.*, coalesce(Members.MemberCount, 0) AS MemberCount, gc.SchemeAdmin AS SyncableSchemeAdmin"). - From("UserGroups"). + query = s.userGroupsSelectQuery. + Columns("gc.ChannelId", "coalesce(Members.MemberCount, 0) AS MemberCount", "gc.SchemeAdmin AS SyncableSchemeAdmin"). LeftJoin(` (SELECT GroupChannels.ChannelId, GroupChannels.DeleteAt, GroupChannels.GroupId, GroupChannels.SchemeAdmin @@ -1457,21 +1455,19 @@ func (s *SqlGroupStore) GetGroupsAssociatedToChannelsByTeam(teamId string, opts func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, viewRestrictions *model.ViewUsersRestrictions) ([]*model.Group, error) { groupsVar := groups{} - selectQuery := []string{"g.*"} + groupsQuery := s.userGroupsSelectQuery if opts.IncludeMemberCount { - selectQuery = append(selectQuery, "coalesce(Members.MemberCount, 0) AS MemberCount") + groupsQuery = groupsQuery.Column("coalesce(Members.MemberCount, 0) AS MemberCount") } if opts.IncludeChannelMemberCount != "" { - selectQuery = append(selectQuery, "coalesce(ChannelMembers.ChannelMemberCount, 0) AS ChannelMemberCount") + groupsQuery = groupsQuery.Column("coalesce(ChannelMembers.ChannelMemberCount, 0) AS ChannelMemberCount") if opts.IncludeTimezones { - selectQuery = append(selectQuery, "coalesce(ChannelMembers.ChannelMemberTimezonesCount, 0) AS ChannelMemberTimezonesCount") + groupsQuery = groupsQuery.Column("coalesce(ChannelMembers.ChannelMemberTimezonesCount, 0) AS ChannelMemberTimezonesCount") } } - groupsQuery := s.getQueryBuilder().Select(strings.Join(selectQuery, ", ")) - if opts.IncludeMemberCount { countQuery := s.getQueryBuilder(). Select("GroupMembers.GroupId, COUNT(DISTINCT Users.Id) AS MemberCount"). @@ -1488,7 +1484,7 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, return nil, errors.Wrap(err, "get_groups_tosql") } groupsQuery = groupsQuery. - LeftJoin("("+countString+") AS Members ON Members.GroupId = g.Id", params...) + LeftJoin("("+countString+") AS Members ON Members.GroupId = UserGroups.Id", params...) } if opts.IncludeChannelMemberCount != "" { @@ -1521,36 +1517,33 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, } groupsQuery = groupsQuery. - LeftJoin("(SELECT "+selectStr+" FROM ChannelMembers LEFT JOIN GroupMembers ON GroupMembers.UserId = ChannelMembers.UserId AND GroupMembers.DeleteAt = 0 "+joinStr+" WHERE ChannelMembers.ChannelId = ? GROUP BY GroupId) AS ChannelMembers ON ChannelMembers.GroupId = g.Id", opts.IncludeChannelMemberCount) + LeftJoin("(SELECT "+selectStr+" FROM ChannelMembers LEFT JOIN GroupMembers ON GroupMembers.UserId = ChannelMembers.UserId AND GroupMembers.DeleteAt = 0 "+joinStr+" WHERE ChannelMembers.ChannelId = ? GROUP BY GroupId) AS ChannelMembers ON ChannelMembers.GroupId = UserGroups.Id", opts.IncludeChannelMemberCount) } if opts.FilterHasMember != "" { groupsQuery = groupsQuery. - LeftJoin("GroupMembers ON GroupMembers.GroupId = g.Id"). + LeftJoin("GroupMembers ON GroupMembers.GroupId = UserGroups.Id"). Where("GroupMembers.UserId = ?", opts.FilterHasMember). Where("GroupMembers.DeleteAt = 0") } - groupsQuery = groupsQuery. - From("UserGroups g") - if opts.Since > 0 { groupsQuery = groupsQuery.Where(sq.Gt{ - "g.UpdateAt": opts.Since, + "UserGroups.UpdateAt": opts.Since, }) } if opts.FilterArchived { - groupsQuery = groupsQuery.Where("g.DeleteAt > 0") + groupsQuery = groupsQuery.Where("UserGroups.DeleteAt > 0") } else if !opts.IncludeArchived && opts.Since <= 0 { // Mobile needs to return archived groups when the since parameter is set, will need to keep this for backwards compatibility - groupsQuery = groupsQuery.Where("g.DeleteAt = 0") + groupsQuery = groupsQuery.Where("UserGroups.DeleteAt = 0") } if opts.IncludeArchived { - groupsQuery = groupsQuery.OrderBy("CASE WHEN g.DeleteAt = 0 THEN g.DisplayName end, CASE WHEN g.DeleteAt != 0 THEN g.DisplayName END") + groupsQuery = groupsQuery.OrderBy("CASE WHEN UserGroups.DeleteAt = 0 THEN UserGroups.DisplayName end, CASE WHEN UserGroups.DeleteAt != 0 THEN UserGroups.DisplayName END") } else { - groupsQuery = groupsQuery.OrderBy("g.DisplayName") + groupsQuery = groupsQuery.OrderBy("UserGroups.DisplayName") } if perPage != 0 { @@ -1560,7 +1553,7 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, } if opts.FilterAllowReference { - groupsQuery = groupsQuery.Where("g.AllowReference = true") + groupsQuery = groupsQuery.Where("UserGroups.AllowReference = true") } if opts.Q != "" { @@ -1569,12 +1562,12 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, if s.DriverName() == model.DatabaseDriverMysql { operatorKeyword = "LIKE" } - groupsQuery = groupsQuery.Where(fmt.Sprintf("(g.Name %[1]s ? OR g.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern) + groupsQuery = groupsQuery.Where(fmt.Sprintf("(UserGroups.Name %[1]s ? OR UserGroups.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern) } if len(opts.NotAssociatedToTeam) == 26 { groupsQuery = groupsQuery.Where(` - g.Id NOT IN ( + UserGroups.Id NOT IN ( SELECT Id FROM @@ -1590,7 +1583,7 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, if len(opts.NotAssociatedToChannel) == 26 { groupsQuery = groupsQuery.Where(` - g.Id NOT IN ( + UserGroups.Id NOT IN ( SELECT Id FROM @@ -1615,7 +1608,7 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, JOIN Channels ON Channels.TeamId = Teams.Id WHERE Channels.Id = ? - ) THEN g.Id IN ( + ) THEN UserGroups.Id IN ( SELECT GroupId FROM @@ -1637,27 +1630,22 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, } if opts.Source != "" { - groupsQuery = groupsQuery.Where("g.Source = ?", opts.Source) + groupsQuery = groupsQuery.Where("UserGroups.Source = ?", opts.Source) } else if opts.OnlySyncableSources { sources := model.GetSyncableGroupSources() sourcePrefixes := model.GetSyncableGroupSourcePrefixes() orClauses := sq.Or{} if len(sources) > 0 { - orClauses = append(orClauses, sq.Eq{"g.Source": sources}) + orClauses = append(orClauses, sq.Eq{"UserGroups.Source": sources}) } for _, prefix := range sourcePrefixes { - orClauses = append(orClauses, sq.Like{"g.Source": string(prefix) + "%"}) + orClauses = append(orClauses, sq.Like{"UserGroups.Source": string(prefix) + "%"}) } groupsQuery = groupsQuery.Where(orClauses) } - queryString, args, err := groupsQuery.ToSql() - if err != nil { - return nil, errors.Wrap(err, "get_groups_tosql") - } - - if err = s.GetReplica().Select(&groupsVar, queryString, args...); err != nil { + if err := s.GetReplica().SelectBuilder(&groupsVar, groupsQuery); err != nil { return nil, errors.Wrap(err, "failed to find Groups") } @@ -1665,16 +1653,21 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts, } func (s *SqlGroupStore) teamMembersMinusGroupMembersQuery(teamID string, groupIDs []string, isCount bool) sq.SelectBuilder { - var selectStr string + var builder sq.SelectBuilder if isCount { - selectStr = "count(DISTINCT Users.Id)" + builder = s.getQueryBuilder().Select("count(DISTINCT Users.Id)") } else { - tmpl := "Users.*, coalesce(TeamMembers.SchemeGuest, false) SchemeGuest, TeamMembers.SchemeAdmin, TeamMembers.SchemeUser, %s AS GroupIDs" + builder = s.getQueryBuilder().Select(). + Columns(getUsersColumns()...). + Column("coalesce(TeamMembers.SchemeGuest, false) SchemeGuest"). + Column("TeamMembers.SchemeAdmin"). + Column("TeamMembers.SchemeUser") + if s.DriverName() == model.DatabaseDriverMysql { - selectStr = fmt.Sprintf(tmpl, "group_concat(UserGroups.Id)") + builder = builder.Column("group_concat(UserGroups.Id) AS GroupIDs") } else { - selectStr = fmt.Sprintf(tmpl, "string_agg(UserGroups.Id, ',')") + builder = builder.Column("string_agg(UserGroups.Id, ',') AS GroupIDs") } } @@ -1686,7 +1679,7 @@ func (s *SqlGroupStore) teamMembersMinusGroupMembersQuery(teamID string, groupID query, _ := subQuery.MustSql() - builder := s.getQueryBuilder().Select(selectStr). + builder = builder. From("TeamMembers"). Join("Teams ON Teams.Id = TeamMembers.TeamId"). Join("Users ON Users.Id = TeamMembers.UserId"). @@ -1738,16 +1731,22 @@ func (s *SqlGroupStore) CountTeamMembersMinusGroupMembers(teamID string, groupID } func (s *SqlGroupStore) channelMembersMinusGroupMembersQuery(channelID string, groupIDs []string, isCount bool) sq.SelectBuilder { - var selectStr string + builder := s.getQueryBuilder().Select() if isCount { - selectStr = "count(DISTINCT Users.Id)" + builder = builder.Column("count(DISTINCT Users.Id)") } else { - tmpl := "Users.*, coalesce(ChannelMembers.SchemeGuest, false) SchemeGuest, ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser, %s AS GroupIDs" + builder = builder.Columns(getUsersColumns()...) + builder = builder.Columns( + "COALESCE(ChannelMembers.SchemeGuest, FALSE) SchemeGuest", + "ChannelMembers.SchemeAdmin", + "ChannelMembers.SchemeUser", + ) + if s.DriverName() == model.DatabaseDriverMysql { - selectStr = fmt.Sprintf(tmpl, "group_concat(UserGroups.Id)") + builder = builder.Column("group_concat(UserGroups.Id) AS GroupIDs") } else { - selectStr = fmt.Sprintf(tmpl, "string_agg(UserGroups.Id, ',')") + builder = builder.Column("string_agg(UserGroups.Id, ',') AS GroupIDs") } } @@ -1759,7 +1758,7 @@ func (s *SqlGroupStore) channelMembersMinusGroupMembersQuery(channelID string, g query, _ := subQuery.MustSql() - builder := s.getQueryBuilder().Select(selectStr). + builder = builder. From("ChannelMembers"). Join("Channels ON Channels.Id = ChannelMembers.ChannelId"). Join("Users ON Users.Id = ChannelMembers.UserId").