Migrate ChannelStore.UpdateLastViewedAt to squirrel (#19439)
Fixes https://github.com/mattermost/mattermost-server/issues/19332 ```release-note NONE ``` Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
de0d95f72b
Коммит
d5b24e383d
@@ -2431,7 +2431,6 @@ func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: convert to squirrel (https://github.com/mattermost/mattermost-server/issues/19332)
|
|
||||||
func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string, updateThreads bool) (map[string]int64, error) {
|
func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string, updateThreads bool) (map[string]int64, error) {
|
||||||
var threadsToUpdate []string
|
var threadsToUpdate []string
|
||||||
now := model.GetMillis()
|
now := model.GetMillis()
|
||||||
@@ -2443,38 +2442,50 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keys, props := MapStringsToQueryParams(channelIds, "Channel")
|
lastPostAtTimes := []struct {
|
||||||
props["UserId"] = userId
|
|
||||||
|
|
||||||
var lastPostAtTimes []struct {
|
|
||||||
Id string
|
Id string
|
||||||
LastPostAt int64
|
LastPostAt int64
|
||||||
TotalMsgCount int64
|
TotalMsgCount int64
|
||||||
TotalMsgCountRoot int64
|
TotalMsgCountRoot int64
|
||||||
}
|
}{}
|
||||||
|
|
||||||
|
// We use the question placeholder format for both databases, because
|
||||||
|
// we replace that with the dollar format later on.
|
||||||
|
// It's needed to support the prefix CTE query. See: https://github.com/Masterminds/squirrel/issues/285.
|
||||||
|
query := sq.StatementBuilder.PlaceholderFormat(sq.Question).
|
||||||
|
Select("Id, LastPostAt, TotalMsgCount, TotalMsgCountRoot").
|
||||||
|
From("Channels").
|
||||||
|
Where(sq.Eq{"Id": channelIds})
|
||||||
|
|
||||||
query := `SELECT Id, LastPostAt, TotalMsgCount, TotalMsgCountRoot FROM Channels WHERE Id IN ` + keys
|
|
||||||
// TODO: use a CTE for mysql too when version 8 becomes the minimum supported version.
|
// TODO: use a CTE for mysql too when version 8 becomes the minimum supported version.
|
||||||
if s.DriverName() == model.DatabaseDriverPostgres {
|
if s.DriverName() == model.DatabaseDriverPostgres {
|
||||||
query = `WITH c AS ( ` + query + `),
|
with := query.Prefix("WITH c AS (").Suffix(") ,")
|
||||||
updated AS (
|
update := sq.StatementBuilder.PlaceholderFormat(sq.Question).
|
||||||
UPDATE
|
Update("ChannelMembers cm").
|
||||||
ChannelMembers cm
|
Set("MentionCount", 0).
|
||||||
SET
|
Set("MentionCountRoot", 0).
|
||||||
MentionCount = 0,
|
Set("MsgCount", sq.Expr("greatest(cm.MsgCount, c.TotalMsgCount)")).
|
||||||
MentionCountRoot = 0,
|
Set("MsgCountRoot", sq.Expr("greatest(cm.MsgCountRoot, c.TotalMsgCountRoot)")).
|
||||||
MsgCount = greatest(cm.MsgCount, c.TotalMsgCount),
|
Set("LastViewedAt", sq.Expr("greatest(cm.LastViewedAt, c.LastPostAt)")).
|
||||||
MsgCountRoot = greatest(cm.MsgCountRoot, c.TotalMsgCountRoot),
|
Set("LastUpdateAt", sq.Expr("greatest(cm.LastViewedAt, c.LastPostAt)")).
|
||||||
LastViewedAt = greatest(cm.LastViewedAt, c.LastPostAt),
|
SuffixExpr(sq.Expr("FROM c WHERE cm.UserId = ? AND c.Id = cm.ChannelId", userId))
|
||||||
LastUpdateAt = greatest(cm.LastViewedAt, c.LastPostAt)
|
updateWrap := update.Prefix("updated AS (").Suffix(")")
|
||||||
FROM c
|
query = with.SuffixExpr(updateWrap).Suffix("SELECT Id, LastPostAt FROM c")
|
||||||
WHERE cm.UserId = :UserId
|
|
||||||
AND c.Id=cm.ChannelId
|
|
||||||
)
|
|
||||||
SELECT Id, LastPostAt FROM c`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := s.GetMaster().Select(&lastPostAtTimes, query, props)
|
sql, args, err := query.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "UpdateLastViewedAt_CTE_Tosql")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.DriverName() == model.DatabaseDriverPostgres {
|
||||||
|
sql, err = sq.Dollar.ReplacePlaceholders(sql)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "UpdateLastViewedAt_ReplacePlaceholders")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.GetMasterX().Select(&lastPostAtTimes, sql, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to find ChannelMembers data with userId=%s and channelId in %v", userId, channelIds)
|
return nil, errors.Wrapf(err, "failed to find ChannelMembers data with userId=%s and channelId in %v", userId, channelIds)
|
||||||
}
|
}
|
||||||
@@ -2494,39 +2505,42 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
|||||||
return times, nil
|
return times, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
msgCountQuery := ""
|
var msgCountQuery, msgCountQueryRoot, lastViewedQuery = sq.Case("ChannelId"), sq.Case("ChannelId"), sq.Case("ChannelId")
|
||||||
msgCountQueryRoot := ""
|
|
||||||
lastViewedQuery := ""
|
|
||||||
|
|
||||||
for index, t := range lastPostAtTimes {
|
for _, t := range lastPostAtTimes {
|
||||||
times[t.Id] = t.LastPostAt
|
times[t.Id] = t.LastPostAt
|
||||||
|
|
||||||
props["msgCount"+strconv.Itoa(index)] = t.TotalMsgCount
|
msgCountQuery = msgCountQuery.When(
|
||||||
msgCountQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCount, :msgCount%d) ", index, index)
|
sq.Expr("?", t.Id),
|
||||||
|
sq.Expr("GREATEST(MsgCount, ?)", t.TotalMsgCount))
|
||||||
|
|
||||||
props["msgCountRoot"+strconv.Itoa(index)] = t.TotalMsgCountRoot
|
msgCountQueryRoot = msgCountQueryRoot.When(
|
||||||
msgCountQueryRoot += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCountRoot, :msgCountRoot%d) ", index, index)
|
sq.Expr("?", t.Id),
|
||||||
|
sq.Expr("GREATEST(MsgCountRoot, ?)", t.TotalMsgCountRoot))
|
||||||
|
|
||||||
props["lastViewed"+strconv.Itoa(index)] = t.LastPostAt
|
lastViewedQuery = lastViewedQuery.When(
|
||||||
lastViewedQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(LastViewedAt, :lastViewed%d) ", index, index)
|
sq.Expr("?", t.Id),
|
||||||
|
sq.Expr("GREATEST(LastViewedAt, ?)", t.LastPostAt))
|
||||||
props["channelId"+strconv.Itoa(index)] = t.Id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateQuery := `UPDATE
|
updateQuery := s.getQueryBuilder().Update("ChannelMembers").
|
||||||
ChannelMembers
|
Set("MentionCount", 0).
|
||||||
SET
|
Set("MentionCountRoot", 0).
|
||||||
MentionCount = 0,
|
Set("MsgCount", msgCountQuery).
|
||||||
MentionCountRoot = 0,
|
Set("MsgCountRoot", msgCountQueryRoot).
|
||||||
MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
|
Set("LastViewedAt", lastViewedQuery).
|
||||||
MsgCountRoot = CASE ChannelId ` + msgCountQueryRoot + ` END,
|
Set("LastUpdateAt", sq.Expr("LastViewedAt")).
|
||||||
LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
|
Where(sq.Eq{
|
||||||
LastUpdateAt = LastViewedAt
|
"UserId": userId,
|
||||||
WHERE
|
"ChannelId": channelIds,
|
||||||
UserId = :UserId
|
})
|
||||||
AND ChannelId IN ` + keys
|
|
||||||
|
|
||||||
if _, err := s.GetMaster().Exec(updateQuery, props); err != nil {
|
sql, args, err = updateQuery.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "UpdateLastViewedAt_Update_Tosql")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := s.GetMasterX().Exec(sql, args...); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to update ChannelMembers with userId=%s and channelId in %v", userId, channelIds)
|
return nil, errors.Wrapf(err, "failed to update ChannelMembers with userId=%s and channelId in %v", userId, channelIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user