MM-62155: Avoid SELECT * in team_store.go (#30464)
* MM-62155: Avoid SELECT * in team_store.go - Added explicit column lists for all SELECT queries - Created teamSelectQuery for reused queries - Replaced raw SQL queries with query builder pattern * Refactor getTeamMembersWithSchemeSelectQuery to use teamMembersQuery builder Instead of duplicating TeamMembers columns, use the existing builder to avoid redundancy. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Remove redundant comments from getTeamMembersWithSchemeSelectQuery 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e90b0ca2a1
Коммит
63e85a3a2b
@@ -25,7 +25,8 @@ const (
|
|||||||
type SqlTeamStore struct {
|
type SqlTeamStore struct {
|
||||||
*SqlStore
|
*SqlStore
|
||||||
|
|
||||||
teamsQuery sq.SelectBuilder
|
teamsQuery sq.SelectBuilder
|
||||||
|
teamMembersQuery sq.SelectBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
type teamMember struct {
|
type teamMember struct {
|
||||||
@@ -71,7 +72,6 @@ type teamMemberWithSchemeRolesList []teamMemberWithSchemeRoles
|
|||||||
func teamMemberSliceColumns() []string {
|
func teamMemberSliceColumns() []string {
|
||||||
return []string{"TeamId", "UserId", "Roles", "DeleteAt", "SchemeUser", "SchemeAdmin", "SchemeGuest", "CreateAt"}
|
return []string{"TeamId", "UserId", "Roles", "DeleteAt", "SchemeUser", "SchemeAdmin", "SchemeGuest", "CreateAt"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func teamMemberToSlice(member *model.TeamMember) []any {
|
func teamMemberToSlice(member *model.TeamMember) []any {
|
||||||
resultSlice := []any{}
|
resultSlice := []any{}
|
||||||
resultSlice = append(resultSlice, member.TeamId)
|
resultSlice = append(resultSlice, member.TeamId)
|
||||||
@@ -213,8 +213,39 @@ func newSqlTeamStore(sqlStore *SqlStore) store.TeamStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.teamsQuery = s.getQueryBuilder().
|
s.teamsQuery = s.getQueryBuilder().
|
||||||
Select("Teams.*").
|
Select(
|
||||||
|
"Teams.Id",
|
||||||
|
"Teams.CreateAt",
|
||||||
|
"Teams.UpdateAt",
|
||||||
|
"Teams.DeleteAt",
|
||||||
|
"Teams.DisplayName",
|
||||||
|
"Teams.Name",
|
||||||
|
"Teams.Description",
|
||||||
|
"Teams.Email",
|
||||||
|
"Teams.Type",
|
||||||
|
"Teams.CompanyName",
|
||||||
|
"Teams.AllowedDomains",
|
||||||
|
"Teams.InviteId",
|
||||||
|
"Teams.AllowOpenInvite",
|
||||||
|
"Teams.LastTeamIconUpdate",
|
||||||
|
"Teams.SchemeId",
|
||||||
|
"Teams.GroupConstrained",
|
||||||
|
"Teams.CloudLimitsArchived",
|
||||||
|
).
|
||||||
From("Teams")
|
From("Teams")
|
||||||
|
|
||||||
|
s.teamMembersQuery = s.getQueryBuilder().
|
||||||
|
Select(
|
||||||
|
"TeamMembers.TeamId",
|
||||||
|
"TeamMembers.UserId",
|
||||||
|
"TeamMembers.Roles",
|
||||||
|
"TeamMembers.DeleteAt",
|
||||||
|
"TeamMembers.SchemeUser",
|
||||||
|
"TeamMembers.SchemeAdmin",
|
||||||
|
"TeamMembers.SchemeGuest",
|
||||||
|
"TeamMembers.CreateAt",
|
||||||
|
).
|
||||||
|
From("TeamMembers")
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +287,9 @@ func (s SqlTeamStore) Update(team *model.Team) (*model.Team, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oldTeam := model.Team{}
|
oldTeam := model.Team{}
|
||||||
err := s.GetMaster().Get(&oldTeam, `SELECT * FROM Teams WHERE Id=?`, team.Id)
|
query := s.teamsQuery.Where(sq.Eq{"Id": team.Id})
|
||||||
|
|
||||||
|
err := s.GetMaster().GetBuilder(&oldTeam, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to get Team with id=%s", team.Id)
|
return nil, errors.Wrapf(err, "failed to get Team with id=%s", team.Id)
|
||||||
}
|
}
|
||||||
@@ -294,7 +327,10 @@ func (s SqlTeamStore) Update(team *model.Team) (*model.Team, error) {
|
|||||||
// http.StatusNotFound in the StatusCode field.
|
// http.StatusNotFound in the StatusCode field.
|
||||||
func (s SqlTeamStore) Get(id string) (*model.Team, error) {
|
func (s SqlTeamStore) Get(id string) (*model.Team, error) {
|
||||||
team := model.Team{}
|
team := model.Team{}
|
||||||
if err := s.GetReplica().Get(&team, `SELECT * FROM Teams WHERE Id=?`, id); err != nil {
|
|
||||||
|
query := s.teamsQuery.Where(sq.Eq{"Id": id})
|
||||||
|
|
||||||
|
if err := s.GetReplica().GetBuilder(&team, query); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, store.NewErrNotFound("Team", id)
|
return nil, store.NewErrNotFound("Team", id)
|
||||||
}
|
}
|
||||||
@@ -308,17 +344,10 @@ func (s SqlTeamStore) Get(id string) (*model.Team, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlTeamStore) GetMany(ids []string) ([]*model.Team, error) {
|
func (s SqlTeamStore) GetMany(ids []string) ([]*model.Team, error) {
|
||||||
query := s.getQueryBuilder().
|
query := s.teamsQuery.Where(sq.Eq{"Teams.Id": ids})
|
||||||
Select("*").
|
|
||||||
From("Teams").
|
|
||||||
Where(sq.Eq{"Id": ids})
|
|
||||||
sql, args, err := query.ToSql()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "getmany_tosql")
|
|
||||||
}
|
|
||||||
|
|
||||||
teams := []*model.Team{}
|
teams := []*model.Team{}
|
||||||
err = s.GetReplica().Select(&teams, sql, args...)
|
err := s.GetReplica().SelectBuilder(&teams, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to get teams with ids %v", ids)
|
return nil, errors.Wrapf(err, "failed to get teams with ids %v", ids)
|
||||||
}
|
}
|
||||||
@@ -353,7 +382,10 @@ func (s SqlTeamStore) GetByInviteId(inviteId string) (*model.Team, error) {
|
|||||||
|
|
||||||
func (s SqlTeamStore) GetByEmptyInviteID() ([]*model.Team, error) {
|
func (s SqlTeamStore) GetByEmptyInviteID() ([]*model.Team, error) {
|
||||||
teams := []*model.Team{}
|
teams := []*model.Team{}
|
||||||
err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE InviteId = ''")
|
|
||||||
|
query := s.teamsQuery.Where(sq.Eq{"InviteId": ""})
|
||||||
|
|
||||||
|
err := s.GetReplica().SelectBuilder(&teams, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to find Teams with empty InviteID")
|
return nil, errors.Wrap(err, "failed to find Teams with empty InviteID")
|
||||||
}
|
}
|
||||||
@@ -621,15 +653,11 @@ func (s SqlTeamStore) GetAllPage(offset int, limit int, opts *model.TeamSearch)
|
|||||||
// GetTeamsByUserId returns from the database all teams that userId belongs to.
|
// GetTeamsByUserId returns from the database all teams that userId belongs to.
|
||||||
func (s SqlTeamStore) GetTeamsByUserId(userId string) ([]*model.Team, error) {
|
func (s SqlTeamStore) GetTeamsByUserId(userId string) ([]*model.Team, error) {
|
||||||
teams := []*model.Team{}
|
teams := []*model.Team{}
|
||||||
query, args, err := s.teamsQuery.
|
query := s.teamsQuery.
|
||||||
Join("TeamMembers ON TeamMembers.TeamId = Teams.Id").
|
Join("TeamMembers ON TeamMembers.TeamId = Teams.Id").
|
||||||
Where(sq.Eq{"TeamMembers.UserId": userId, "TeamMembers.DeleteAt": 0, "Teams.DeleteAt": 0}).ToSql()
|
Where(sq.Eq{"TeamMembers.UserId": userId, "TeamMembers.DeleteAt": 0, "Teams.DeleteAt": 0})
|
||||||
|
|
||||||
if err != nil {
|
if err := s.GetReplica().SelectBuilder(&teams, query); err != nil {
|
||||||
return nil, errors.Wrap(err, "team_tosql")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = s.GetReplica().Select(&teams, query, args...); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to find Teams")
|
return nil, errors.Wrap(err, "failed to find Teams")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,13 +666,11 @@ func (s SqlTeamStore) GetTeamsByUserId(userId string) ([]*model.Team, error) {
|
|||||||
|
|
||||||
// GetAllPrivateTeamListing returns all private teams.
|
// GetAllPrivateTeamListing returns all private teams.
|
||||||
func (s SqlTeamStore) GetAllPrivateTeamListing() ([]*model.Team, error) {
|
func (s SqlTeamStore) GetAllPrivateTeamListing() ([]*model.Team, error) {
|
||||||
query, args, err := s.teamsQuery.Where(sq.Eq{"AllowOpenInvite": false}).
|
query := s.teamsQuery.Where(sq.Eq{"AllowOpenInvite": false}).
|
||||||
OrderBy("DisplayName").ToSql()
|
OrderBy("DisplayName")
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "team_tosql")
|
|
||||||
}
|
|
||||||
data := []*model.Team{}
|
data := []*model.Team{}
|
||||||
if err = s.GetReplica().Select(&data, query, args...); err != nil {
|
if err := s.GetReplica().SelectBuilder(&data, query); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to find Teams")
|
return nil, errors.Wrap(err, "failed to find Teams")
|
||||||
}
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
@@ -652,15 +678,11 @@ func (s SqlTeamStore) GetAllPrivateTeamListing() ([]*model.Team, error) {
|
|||||||
|
|
||||||
// GetAllTeamListing returns all public teams.
|
// GetAllTeamListing returns all public teams.
|
||||||
func (s SqlTeamStore) GetAllTeamListing() ([]*model.Team, error) {
|
func (s SqlTeamStore) GetAllTeamListing() ([]*model.Team, error) {
|
||||||
query, args, err := s.teamsQuery.Where(sq.Eq{"AllowOpenInvite": true}).
|
query := s.teamsQuery.Where(sq.Eq{"AllowOpenInvite": true}).
|
||||||
OrderBy("DisplayName").ToSql()
|
OrderBy("DisplayName")
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "team_tosql")
|
|
||||||
}
|
|
||||||
|
|
||||||
data := []*model.Team{}
|
data := []*model.Team{}
|
||||||
if err = s.GetReplica().Select(&data, query, args...); err != nil {
|
if err := s.GetReplica().SelectBuilder(&data, query); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to find Teams")
|
return nil, errors.Wrap(err, "failed to find Teams")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,16 +730,14 @@ func (s SqlTeamStore) AnalyticsTeamCount(opts *model.TeamSearch) (int64, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlTeamStore) getTeamMembersWithSchemeSelectQuery() sq.SelectBuilder {
|
func (s SqlTeamStore) getTeamMembersWithSchemeSelectQuery() sq.SelectBuilder {
|
||||||
return s.getQueryBuilder().
|
query := s.teamMembersQuery.
|
||||||
Select(
|
Column("TeamScheme.DefaultTeamGuestRole TeamSchemeDefaultGuestRole").
|
||||||
"TeamMembers.*",
|
Column("TeamScheme.DefaultTeamUserRole TeamSchemeDefaultUserRole").
|
||||||
"TeamScheme.DefaultTeamGuestRole TeamSchemeDefaultGuestRole",
|
Column("TeamScheme.DefaultTeamAdminRole TeamSchemeDefaultAdminRole").
|
||||||
"TeamScheme.DefaultTeamUserRole TeamSchemeDefaultUserRole",
|
|
||||||
"TeamScheme.DefaultTeamAdminRole TeamSchemeDefaultAdminRole",
|
|
||||||
).
|
|
||||||
From("TeamMembers").
|
|
||||||
LeftJoin("Teams ON TeamMembers.TeamId = Teams.Id").
|
LeftJoin("Teams ON TeamMembers.TeamId = Teams.Id").
|
||||||
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id")
|
LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id")
|
||||||
|
|
||||||
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlTeamStore) SaveMultipleMembers(members []*model.TeamMember, maxUsersPerTeam int) ([]*model.TeamMember, error) {
|
func (s SqlTeamStore) SaveMultipleMembers(members []*model.TeamMember, maxUsersPerTeam int) ([]*model.TeamMember, error) {
|
||||||
@@ -1288,8 +1308,13 @@ func (s SqlTeamStore) MigrateTeamMembers(fromTeamId string, fromUserId string) (
|
|||||||
}
|
}
|
||||||
defer finalizeTransactionX(transaction, &err)
|
defer finalizeTransactionX(transaction, &err)
|
||||||
|
|
||||||
|
query := s.teamMembersQuery.
|
||||||
|
Where(sq.Expr("(TeamMembers.TeamId, TeamMembers.UserId) > (?, ?)", fromTeamId, fromUserId)).
|
||||||
|
OrderBy("TeamMembers.TeamId, TeamMembers.UserId").
|
||||||
|
Limit(100)
|
||||||
|
|
||||||
teamMembers := []teamMember{}
|
teamMembers := []teamMember{}
|
||||||
if err := transaction.Select(&teamMembers, "SELECT * from TeamMembers WHERE (TeamId, UserId) > (?, ?) ORDER BY TeamId, UserId LIMIT 100", fromTeamId, fromUserId); err != nil {
|
if err := transaction.SelectBuilder(&teamMembers, query); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to find TeamMembers")
|
return nil, errors.Wrap(err, "failed to find TeamMembers")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1379,8 +1404,13 @@ func (s SqlTeamStore) ClearAllCustomRoleAssignments() (err error) {
|
|||||||
}
|
}
|
||||||
defer finalizeTransactionX(transaction, &err)
|
defer finalizeTransactionX(transaction, &err)
|
||||||
|
|
||||||
|
query := s.teamMembersQuery.
|
||||||
|
Where(sq.Expr("(TeamMembers.TeamId, TeamMembers.UserId) > (?, ?)", lastTeamId, lastUserId)).
|
||||||
|
OrderBy("TeamMembers.TeamId, TeamMembers.UserId").
|
||||||
|
Limit(1000)
|
||||||
|
|
||||||
teamMembers := []*teamMember{}
|
teamMembers := []*teamMember{}
|
||||||
if err := transaction.Select(&teamMembers, "SELECT * from TeamMembers WHERE (TeamId, UserId) > (?, ?) ORDER BY TeamId, UserId LIMIT 1000", lastTeamId, lastUserId); err != nil {
|
if err := transaction.SelectBuilder(&teamMembers, query); err != nil {
|
||||||
return errors.Wrap(err, "failed to find TeamMembers")
|
return errors.Wrap(err, "failed to find TeamMembers")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1605,9 +1635,7 @@ func (s SqlTeamStore) UpdateMembersRole(teamID string, adminIDs []string) (_ []*
|
|||||||
// On MySQL it's not possible to update a table and select from it in the same query.
|
// On MySQL it's not possible to update a table and select from it in the same query.
|
||||||
// A SELECT and a UPDATE query are needed.
|
// A SELECT and a UPDATE query are needed.
|
||||||
// Once we only support PostgreSQL, this can be done in a single query using RETURNING.
|
// Once we only support PostgreSQL, this can be done in a single query using RETURNING.
|
||||||
query, args, err := s.getQueryBuilder().
|
query, args, err := s.teamMembersQuery.
|
||||||
Select("*").
|
|
||||||
From("TeamMembers").
|
|
||||||
Where(sq.Eq{"TeamId": teamID, "DeleteAt": 0}).
|
Where(sq.Eq{"TeamId": teamID, "DeleteAt": 0}).
|
||||||
Where(sq.Or{sq.Eq{"SchemeGuest": false}, sq.Expr("SchemeGuest IS NULL")}).
|
Where(sq.Or{sq.Eq{"SchemeGuest": false}, sq.Expr("SchemeGuest IS NULL")}).
|
||||||
Where(
|
Where(
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user