Refactor SQL queries in store/sqlstore/channel_member_history_store.go to use the squirrel builder (#15529)

Этот коммит содержится в:
Jaime Cepeda
2020-09-23 01:32:03 +02:00
коммит произвёл GitHub
родитель 31e99920ef
Коммит f3cb2538a7

Просмотреть файл

@@ -5,6 +5,9 @@ package sqlstore
import ( import (
"database/sql" "database/sql"
"fmt"
sq "github.com/Masterminds/squirrel"
"github.com/mattermost/mattermost-server/v5/mlog" "github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/model"
@@ -46,15 +49,18 @@ func (s SqlChannelMemberHistoryStore) LogJoinEvent(userId string, channelId stri
} }
func (s SqlChannelMemberHistoryStore) LogLeaveEvent(userId string, channelId string, leaveTime int64) error { func (s SqlChannelMemberHistoryStore) LogLeaveEvent(userId string, channelId string, leaveTime int64) error {
query := ` query, params, err := s.getQueryBuilder().
UPDATE ChannelMemberHistory Update("ChannelMemberHistory").
SET LeaveTime = :LeaveTime Set("LeaveTime", leaveTime).
WHERE UserId = :UserId Where(sq.And{
AND ChannelId = :ChannelId sq.Eq{"UserId": userId},
AND LeaveTime IS NULL` sq.Eq{"ChannelId": channelId},
sq.Eq{"LeaveTime": nil},
params := map[string]interface{}{"UserId": userId, "ChannelId": channelId, "LeaveTime": leaveTime} }).ToSql()
sqlResult, err := s.GetMaster().Exec(query, params) if err != nil {
return errors.Wrap(err, "channel_member_history_to_sql")
}
sqlResult, err := s.GetMaster().Exec(query, params...)
if err != nil { if err != nil {
return errors.Wrapf(err, "LogLeaveEvent userId=%s channelId=%s leaveTime=%d", userId, channelId, leaveTime) return errors.Wrapf(err, "LogLeaveEvent userId=%s channelId=%s leaveTime=%d", userId, channelId, leaveTime)
} }
@@ -81,7 +87,6 @@ func (s SqlChannelMemberHistoryStore) GetUsersInChannelDuring(startTime int64, e
} }
return channelMemberHistories, nil return channelMemberHistories, nil
} }
// the export period starts before the ChannelMemberHistory table was introduced, so we need to fake the // the export period starts before the ChannelMemberHistory table was introduced, so we need to fake the
// data by assuming that anybody who has ever joined the channel in question was present during the export period. // data by assuming that anybody who has ever joined the channel in question was present during the export period.
// this may not always be true, but it's better than saying that somebody wasn't there when they were // this may not always be true, but it's better than saying that somebody wasn't there when they were
@@ -96,8 +101,11 @@ func (s SqlChannelMemberHistoryStore) hasDataAtOrBefore(time int64) (bool, error
type NullableCountResult struct { type NullableCountResult struct {
Min sql.NullInt64 Min sql.NullInt64
} }
query, _, err := s.getQueryBuilder().Select("MIN(JoinTime) as Min").From("ChannelMemberHistory").ToSql()
if err != nil {
return false, errors.Wrap(err, "channel_member_history_to_sql")
}
var result NullableCountResult var result NullableCountResult
query := "SELECT MIN(JoinTime) AS Min FROM ChannelMemberHistory"
if err := s.GetReplica().SelectOne(&result, query); err != nil { if err := s.GetReplica().SelectOne(&result, query); err != nil {
return false, err return false, err
} else if result.Min.Valid { } else if result.Min.Valid {
@@ -109,24 +117,25 @@ func (s SqlChannelMemberHistoryStore) hasDataAtOrBefore(time int64) (bool, error
} }
func (s SqlChannelMemberHistoryStore) getFromChannelMemberHistoryTable(startTime int64, endTime int64, channelId string) ([]*model.ChannelMemberHistoryResult, error) { func (s SqlChannelMemberHistoryStore) getFromChannelMemberHistoryTable(startTime int64, endTime int64, channelId string) ([]*model.ChannelMemberHistoryResult, error) {
query := ` query, args, err := s.getQueryBuilder().
SELECT Select("cmh.*, u.Email, u.Username, Bots.UserId IS NOT NULL AS IsBot, u.DeleteAt AS UserDeleteAt").
cmh.*, From("ChannelMemberHistory cmh").
u.Email, Join("Users u ON cmh.UserId = u.Id").
u.Username, LeftJoin("Bots ON Bots.UserId = u.Id").
Bots.UserId IS NOT NULL AS IsBot, Where(sq.And{
u.DeleteAt AS UserDeleteAt sq.Eq{"cmh.ChannelId": channelId},
FROM ChannelMemberHistory cmh sq.LtOrEq{"cmh.JoinTime": endTime},
INNER JOIN Users u ON cmh.UserId = u.Id sq.Or{
LEFT JOIN Bots ON Bots.UserId = u.Id sq.Eq{"cmh.LeaveTime": nil},
WHERE cmh.ChannelId = :ChannelId sq.GtOrEq{"cmh.LeaveTime": startTime},
AND cmh.JoinTime <= :EndTime },
AND (cmh.LeaveTime IS NULL OR cmh.LeaveTime >= :StartTime) }).
ORDER BY cmh.JoinTime ASC` OrderBy("cmh.JoinTime ASC").ToSql()
if err != nil {
params := map[string]interface{}{"ChannelId": channelId, "StartTime": startTime, "EndTime": endTime} return nil, errors.Wrap(err, "channel_member_history_to_sql")
}
var histories []*model.ChannelMemberHistoryResult var histories []*model.ChannelMemberHistoryResult
if _, err := s.GetReplica().Select(&histories, query, params); err != nil { if _, err := s.GetReplica().Select(&histories, query, args...); err != nil {
return nil, err return nil, err
} }
@@ -134,22 +143,19 @@ func (s SqlChannelMemberHistoryStore) getFromChannelMemberHistoryTable(startTime
} }
func (s SqlChannelMemberHistoryStore) getFromChannelMembersTable(startTime int64, endTime int64, channelId string) ([]*model.ChannelMemberHistoryResult, error) { func (s SqlChannelMemberHistoryStore) getFromChannelMembersTable(startTime int64, endTime int64, channelId string) ([]*model.ChannelMemberHistoryResult, error) {
query := ` query, args, err := s.getQueryBuilder().
SELECT DISTINCT Select("ch.ChannelId, ch.UserId, u.Email, u.Username, Bots.UserId IS NOT NULL AS IsBot, u.DeleteAt AS UserDeleteAt").
ch.ChannelId, Distinct().
ch.UserId, From("ChannelMembers ch").
u.Email, Join("Users u ON ch.UserId = u.id").
u.Username, LeftJoin("Bots ON Bots.UserId = u.id").
Bots.UserId IS NOT NULL AS IsBot, Where(sq.Eq{"ch.ChannelId": channelId}).ToSql()
u.DeleteAt AS UserDeleteAt if err != nil {
FROM ChannelMembers AS ch return nil, errors.Wrap(err, "channel_member_history_to_sql")
INNER JOIN Users AS u ON ch.UserId = u.id }
LEFT JOIN Bots ON Bots.UserId = u.Id
WHERE ch.ChannelId = :ChannelId`
params := map[string]interface{}{"ChannelId": channelId}
var histories []*model.ChannelMemberHistoryResult var histories []*model.ChannelMemberHistoryResult
if _, err := s.GetReplica().Select(&histories, query, params); err != nil { if _, err := s.GetReplica().Select(&histories, query, args...); err != nil {
return nil, err return nil, err
} }
// we have to fill in the join/leave times, because that data doesn't exist in the channel members table // we have to fill in the join/leave times, because that data doesn't exist in the channel members table
@@ -161,26 +167,43 @@ func (s SqlChannelMemberHistoryStore) getFromChannelMembersTable(startTime int64
} }
func (s SqlChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, error) { func (s SqlChannelMemberHistoryStore) PermanentDeleteBatch(endTime int64, limit int64) (int64, error) {
var query string var (
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { query string
query = args []interface{}
`DELETE FROM ChannelMemberHistory err error
WHERE ctid IN ( )
SELECT ctid FROM ChannelMemberHistory
WHERE LeaveTime IS NOT NULL
AND LeaveTime <= :EndTime
LIMIT :Limit
);`
} else {
query =
`DELETE FROM ChannelMemberHistory
WHERE LeaveTime IS NOT NULL
AND LeaveTime <= :EndTime
LIMIT :Limit`
}
params := map[string]interface{}{"EndTime": endTime, "Limit": limit} if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
sqlResult, err := s.GetMaster().Exec(query, params) var innerSelect string
innerSelect, args, err = s.getQueryBuilder().
Select("ctid").
From("ChannelMemberHistory").
Where(sq.And{
sq.NotEq{"LeaveTime": nil},
sq.LtOrEq{"LeaveTime": endTime},
}).Limit(uint64(limit)).
ToSql()
if err != nil {
return 0, errors.Wrap(err, "channel_member_history_to_sql")
}
query, _, err = s.getQueryBuilder().
Delete("ChannelMemberHistory").
Where(fmt.Sprintf(
"ctid IN (%s)", innerSelect,
)).ToSql()
} else {
query, args, err = s.getQueryBuilder().
Delete("ChannelMemberHistory").
Where(sq.And{
sq.NotEq{"LeaveTime": nil},
sq.LtOrEq{"LeaveTime": endTime},
}).
Limit(uint64(limit)).ToSql()
}
if err != nil {
return 0, errors.Wrap(err, "channel_member_history_to_sql")
}
sqlResult, err := s.GetMaster().Exec(query, args...)
if err != nil { if err != nil {
return 0, errors.Wrapf(err, "PermanentDeleteBatch endTime=%d limit=%d", endTime, limit) return 0, errors.Wrapf(err, "PermanentDeleteBatch endTime=%d limit=%d", endTime, limit)
} }