Migrate Channelstore categories to sqlx (#19506)

Remove db:"-" tags from model.Channel as well.

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2022-02-09 23:09:42 +05:30
коммит произвёл GitHub
родитель 57eafbc6ca
Коммит 2d986ef920
5 изменённых файлов: 143 добавлений и 232 удалений

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

@@ -51,11 +51,11 @@ type Channel struct {
ExtraUpdateAt int64 `json:"extra_update_at"`
CreatorId string `json:"creator_id"`
SchemeId *string `json:"scheme_id"`
Props map[string]interface{} `json:"props" db:"-"`
Props map[string]interface{} `json:"props"`
GroupConstrained *bool `json:"group_constrained"`
Shared *bool `json:"shared"`
TotalMsgCountRoot int64 `json:"total_msg_count_root"`
PolicyID *string `json:"policy_id" db:"-"`
PolicyID *string `json:"policy_id"`
LastRootPostAt int64 `json:"last_root_post_at"`
}

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

@@ -431,84 +431,6 @@ type publicChannel struct {
Purpose string `json:"purpose"`
}
// channelInternal is a struct without the db:"-" tags
// which does not work with sqlx. This would be removed once we
// move to the new migration system.
type channelInternal struct {
Id string
CreateAt int64
UpdateAt int64
DeleteAt int64
TeamId string
Type model.ChannelType
DisplayName string
Name string
Header string
Purpose string
LastPostAt int64
TotalMsgCount int64
ExtraUpdateAt int64
CreatorId string
SchemeId *string
Props map[string]interface{}
GroupConstrained *bool
Shared *bool
TotalMsgCountRoot int64
PolicyId *string
LastRootPostAt int64
}
func (ci *channelInternal) ToModel() *model.Channel {
return &model.Channel{
Id: ci.Id,
CreateAt: ci.CreateAt,
UpdateAt: ci.UpdateAt,
DeleteAt: ci.DeleteAt,
TeamId: ci.TeamId,
Type: ci.Type,
DisplayName: ci.DisplayName,
Name: ci.Name,
Header: ci.Header,
Purpose: ci.Purpose,
LastPostAt: ci.LastPostAt,
TotalMsgCount: ci.TotalMsgCount,
ExtraUpdateAt: ci.ExtraUpdateAt,
CreatorId: ci.CreatorId,
SchemeId: ci.SchemeId,
Props: ci.Props,
GroupConstrained: ci.GroupConstrained,
Shared: ci.Shared,
TotalMsgCountRoot: ci.TotalMsgCountRoot,
PolicyID: ci.PolicyId,
LastRootPostAt: ci.LastRootPostAt,
}
}
type channelWithTeamDataInternal struct {
channelInternal
TeamDisplayName string
TeamName string
TeamUpdateAt int64
}
func (ctd *channelWithTeamDataInternal) ToModel() *model.ChannelWithTeamData {
res := &model.ChannelWithTeamData{
TeamDisplayName: ctd.TeamDisplayName,
TeamName: ctd.TeamName,
TeamUpdateAt: ctd.TeamUpdateAt,
}
res.Channel = *ctd.channelInternal.ToModel()
return res
}
func channelWithTeamDataSliceToModel(channels []*channelWithTeamDataInternal) model.ChannelListWithTeamData {
res := make(model.ChannelListWithTeamData, 0, len(channels))
for _, ch := range channels {
res = append(res, ch.ToModel())
}
return res
}
var allChannelMembersForUserCache = cache.NewLRU(cache.LRUOptions{
Size: AllChannelMembersForUserCacheSize,
})
@@ -1283,13 +1205,13 @@ func (s SqlChannelStore) GetAllChannels(offset, limit int, opts store.ChannelSea
return nil, errors.Wrap(err, "failed to create query")
}
data := []*channelWithTeamDataInternal{}
data := model.ChannelListWithTeamData{}
err = s.GetReplicaX().Select(&data, queryString, args...)
if err != nil {
return nil, errors.Wrap(err, "failed to get all channels")
}
return channelWithTeamDataSliceToModel(data), nil
return data, nil
}
func (s SqlChannelStore) GetAllChannelsCount(opts store.ChannelSearchOpts) (int64, error) {
@@ -1316,7 +1238,7 @@ func (s SqlChannelStore) getAllChannelsQuery(opts store.ChannelSearchOpts, forCo
} else {
selectStr = "c.*, Teams.DisplayName AS TeamDisplayName, Teams.Name AS TeamName, Teams.UpdateAt AS TeamUpdateAt"
if opts.IncludePolicyID {
selectStr += ", RetentionPoliciesChannels.PolicyId"
selectStr += ", RetentionPoliciesChannels.PolicyId AS PolicyID"
}
}
@@ -3222,7 +3144,7 @@ func (s SqlChannelStore) channelSearchQuery(opts *store.ChannelSearchOpts) sq.Se
selectStr += ", t.DisplayName AS TeamDisplayName, t.Name AS TeamName, t.UpdateAt as TeamUpdateAt"
}
if opts.IncludePolicyID {
selectStr += ", RetentionPoliciesChannels.PolicyId"
selectStr += ", RetentionPoliciesChannels.PolicyId AS PolicyID"
}
}
@@ -3314,7 +3236,7 @@ func (s SqlChannelStore) SearchAllChannels(term string, opts store.ChannelSearch
if err != nil {
return nil, 0, errors.Wrap(err, "channel_tosql")
}
channels := []*channelWithTeamDataInternal{}
channels := model.ChannelListWithTeamData{}
if err2 := s.GetReplicaX().Select(&channels, queryString, args...); err2 != nil {
return nil, 0, errors.Wrapf(err2, "failed to find Channels with term='%s'", term)
}
@@ -3335,7 +3257,7 @@ func (s SqlChannelStore) SearchAllChannels(term string, opts store.ChannelSearch
totalCount = int64(len(channels))
}
return channelWithTeamDataSliceToModel(channels), totalCount, nil
return channels, totalCount, nil
}
// TODO: rewrite in squrrel

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

@@ -7,25 +7,24 @@ import (
"fmt"
sq "github.com/Masterminds/squirrel"
"github.com/mattermost/gorp"
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/store"
)
// dbSelecter is an interface used to enable some internal store methods to
// accept both transactions (*gorp.Transaction) and common db handlers (*gorp.DbMap).
// dbSelecter is an interface used to enable some internal store methods
// using both transaction and normal queries.
type dbSelecter interface {
Select(i interface{}, query string, args ...interface{}) ([]interface{}, error)
Select(i interface{}, query string, args ...interface{}) error
}
func (s SqlChannelStore) CreateInitialSidebarCategories(userId, teamId string) (*model.OrderedSidebarCategories, error) {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return nil, errors.Wrap(err, "CreateInitialSidebarCategories: begin_transaction")
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
if err = s.createInitialSidebarCategoriesT(transaction, userId, teamId); err != nil {
return nil, errors.Wrap(err, "CreateInitialSidebarCategories: createInitialSidebarCategoriesT")
@@ -43,7 +42,7 @@ func (s SqlChannelStore) CreateInitialSidebarCategories(userId, teamId string) (
return oc, nil
}
func (s SqlChannelStore) createInitialSidebarCategoriesT(transaction *gorp.Transaction, userId, teamId string) error {
func (s SqlChannelStore) createInitialSidebarCategoriesT(transaction *sqlxTxWrapper, userId, teamId string) error {
selectQuery, selectParams, _ := s.getQueryBuilder().
Select("Type").
From("SidebarCategories").
@@ -53,8 +52,8 @@ func (s SqlChannelStore) createInitialSidebarCategoriesT(transaction *gorp.Trans
"Type": []model.SidebarCategoryType{model.SidebarCategoryFavorites, model.SidebarCategoryChannels, model.SidebarCategoryDirectMessages},
}).ToSql()
var existingTypes []model.SidebarCategoryType
_, err := transaction.Select(&existingTypes, selectQuery, selectParams...)
existingTypes := []model.SidebarCategoryType{}
err := transaction.Select(&existingTypes, selectQuery, selectParams...)
if err != nil {
return errors.Wrap(err, "createInitialSidebarCategoriesT: failed to select existing categories")
}
@@ -75,7 +74,9 @@ func (s SqlChannelStore) createInitialSidebarCategoriesT(transaction *gorp.Trans
return errors.Wrap(err, "createInitialSidebarCategoriesT: failed to migrate favorites to sidebar")
}
if err := transaction.Insert(&model.SidebarCategory{
if _, err := transaction.NamedExec(`INSERT INTO
SidebarCategories(Id, UserId, TeamId, SortOrder, Sorting, Type, DisplayName, Muted, Collapsed)
VALUES(:Id, :UserId, :TeamId, :SortOrder, :Sorting, :Type, :DisplayName, :Muted, :Collapsed)`, &model.SidebarCategory{
DisplayName: "Favorites", // This will be retranslated by the client into the user's locale
Id: favoritesCategoryId,
UserId: userId,
@@ -89,7 +90,9 @@ func (s SqlChannelStore) createInitialSidebarCategoriesT(transaction *gorp.Trans
}
if !hasCategoryOfType[model.SidebarCategoryChannels] {
if err := transaction.Insert(&model.SidebarCategory{
if _, err := transaction.NamedExec(`INSERT INTO
SidebarCategories(Id, UserId, TeamId, SortOrder, Sorting, Type, DisplayName, Muted, Collapsed)
VALUES(:Id, :UserId, :TeamId, :SortOrder, :Sorting, :Type, :DisplayName, :Muted, :Collapsed)`, &model.SidebarCategory{
DisplayName: "Channels", // This will be retranslated by the client into the user's locale
Id: channelsCategoryId,
UserId: userId,
@@ -103,7 +106,9 @@ func (s SqlChannelStore) createInitialSidebarCategoriesT(transaction *gorp.Trans
}
if !hasCategoryOfType[model.SidebarCategoryDirectMessages] {
if err := transaction.Insert(&model.SidebarCategory{
if _, err := transaction.NamedExec(`INSERT INTO
SidebarCategories(Id, UserId, TeamId, SortOrder, Sorting, Type, DisplayName, Muted, Collapsed)
VALUES(:Id, :UserId, :TeamId, :SortOrder, :Sorting, :Type, :DisplayName, :Muted, :Collapsed)`, &model.SidebarCategory{
DisplayName: "Direct Messages", // This will be retranslated by the client into the user's locale
Id: directMessagesCategoryId,
UserId: userId,
@@ -125,9 +130,9 @@ type userMembership struct {
CategoryId string
}
func (s SqlChannelStore) migrateMembershipToSidebar(transaction *gorp.Transaction, runningOrder *int64, sql string, args ...interface{}) ([]userMembership, error) {
var memberships []userMembership
if _, err := transaction.Select(&memberships, sql, args...); err != nil {
func (s SqlChannelStore) migrateMembershipToSidebar(transaction *sqlxTxWrapper, runningOrder *int64, sql string, args ...interface{}) ([]userMembership, error) {
memberships := []userMembership{}
if err := transaction.Select(&memberships, sql, args...); err != nil {
return nil, err
}
@@ -149,7 +154,7 @@ func (s SqlChannelStore) migrateMembershipToSidebar(transaction *gorp.Transactio
return memberships, nil
}
func (s SqlChannelStore) migrateFavoritesToSidebarT(transaction *gorp.Transaction, userId, teamId, favoritesCategoryId string) error {
func (s SqlChannelStore) migrateFavoritesToSidebarT(transaction *sqlxTxWrapper, userId, teamId, favoritesCategoryId string) error {
favoritesQuery, favoritesParams, _ := s.getQueryBuilder().
Select("Preferences.Name").
From("Preferences").
@@ -169,13 +174,15 @@ func (s SqlChannelStore) migrateFavoritesToSidebarT(transaction *gorp.Transactio
"Channels.Name ASC",
).ToSql()
var favoriteChannelIds []string
if _, err := transaction.Select(&favoriteChannelIds, favoritesQuery, favoritesParams...); err != nil {
favoriteChannelIds := []string{}
if err := transaction.Select(&favoriteChannelIds, favoritesQuery, favoritesParams...); err != nil {
return errors.Wrap(err, "migrateFavoritesToSidebarT: unable to get favorite channel IDs")
}
for i, channelId := range favoriteChannelIds {
if err := transaction.Insert(&model.SidebarChannel{
if _, err := transaction.NamedExec(`INSERT INTO
SidebarChannels(ChannelId, UserId, CategoryId, SortOrder)
VALUES(:ChannelId, :UserId, :CategoryId, :SortOrder)`, &model.SidebarChannel{
ChannelId: channelId,
CategoryId: favoritesCategoryId,
UserId: userId,
@@ -191,12 +198,12 @@ func (s SqlChannelStore) migrateFavoritesToSidebarT(transaction *gorp.Transactio
// MigrateFavoritesToSidebarChannels populates the SidebarChannels table by analyzing existing user preferences for favorites
// **IMPORTANT** This function should only be called from the migration task and shouldn't be used by itself
func (s SqlChannelStore) MigrateFavoritesToSidebarChannels(lastUserId string, runningOrder int64) (map[string]interface{}, error) {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return nil, err
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
sb := s.
getQueryBuilder().
@@ -238,12 +245,12 @@ type sidebarCategoryForJoin struct {
}
func (s SqlChannelStore) CreateSidebarCategory(userId, teamId string, newCategory *model.SidebarCategoryWithChannels) (*model.SidebarCategoryWithChannels, error) {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return nil, errors.Wrap(err, "begin_transaction")
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
categoriesWithOrder, err := s.getSidebarCategoriesT(transaction, userId, teamId)
if err != nil {
@@ -277,15 +284,14 @@ func (s SqlChannelStore) CreateSidebarCategory(userId, teamId string, newCategor
Type: model.SidebarCategoryCustom,
Muted: newCategory.Muted,
}
if err = transaction.Insert(category); err != nil {
return nil, errors.Wrap(err, "failed to save SidebarCategory")
if _, err2 := transaction.NamedExec(`INSERT INTO
SidebarCategories(Id, UserId, TeamId, SortOrder, Sorting, Type, DisplayName, Muted, Collapsed)
VALUES(:Id, :UserId, :TeamId, :SortOrder, :Sorting, :Type, :DisplayName, :Muted, :Collapsed)`, category); err2 != nil {
return nil, errors.Wrap(err2, "failed to save SidebarCategory")
}
if len(newCategory.Channels) > 0 {
channelIdsKeys, deleteParams := MapStringsToQueryParams(newCategory.Channels, "ChannelId")
deleteParams["UserId"] = userId
deleteParams["TeamId"] = teamId
placeHolder, channelIdArgs := constructArrayArgs(newCategory.Channels)
// Remove any channels from their previous categories and add them to the new one
var deleteQuery string
if s.DriverName() == model.DatabaseDriverMysql {
@@ -297,9 +303,9 @@ func (s SqlChannelStore) CreateSidebarCategory(userId, teamId string, newCategor
JOIN
SidebarCategories ON SidebarChannels.CategoryId = SidebarCategories.Id
WHERE
SidebarChannels.UserId = :UserId
AND SidebarChannels.ChannelId IN ` + channelIdsKeys + `
AND SidebarCategories.TeamId = :TeamId`
SidebarChannels.UserId = ?
AND SidebarChannels.ChannelId IN ` + placeHolder + `
AND SidebarCategories.TeamId = ?`
} else {
deleteQuery = `
DELETE FROM
@@ -308,36 +314,41 @@ func (s SqlChannelStore) CreateSidebarCategory(userId, teamId string, newCategor
SidebarCategories
WHERE
SidebarChannels.CategoryId = SidebarCategories.Id
AND SidebarChannels.UserId = :UserId
AND SidebarChannels.ChannelId IN ` + channelIdsKeys + `
AND SidebarCategories.TeamId = :TeamId`
AND SidebarChannels.UserId = ?
AND SidebarChannels.ChannelId IN ` + placeHolder + `
AND SidebarCategories.TeamId = ?`
}
_, err = transaction.Exec(deleteQuery, deleteParams)
args := []interface{}{userId}
args = append(args, channelIdArgs...)
args = append(args, teamId)
_, err = transaction.Exec(deleteQuery, args...)
if err != nil {
return nil, errors.Wrap(err, "failed to delete SidebarChannels")
}
var channels []interface{}
insertQuery := s.getQueryBuilder().
Insert("SidebarChannels").
Columns("ChannelId", "UserId", "CategoryId", "SortOrder")
for i, channelID := range newCategory.Channels {
channels = append(channels, &model.SidebarChannel{
ChannelId: channelID,
CategoryId: newCategoryId,
SortOrder: int64(i * model.MinimalSidebarSortDistance),
UserId: userId,
})
insertQuery = insertQuery.Values(channelID, userId, newCategoryId, int64(i*model.MinimalSidebarSortDistance))
}
if err = transaction.Insert(channels...); err != nil {
sql, args, err := insertQuery.ToSql()
if err != nil {
return nil, errors.Wrap(err, "InsertSidebarChannels_Tosql")
}
if _, err := transaction.Exec(sql, args...); err != nil {
return nil, errors.Wrap(err, "failed to save SidebarChannels")
}
}
// now we re-order the categories according to the new order
if err = s.updateSidebarCategoryOrderT(transaction, newOrder); err != nil {
if err := s.updateSidebarCategoryOrderT(transaction, newOrder); err != nil {
return nil, err
}
if err = transaction.Commit(); err != nil {
if err := transaction.Commit(); err != nil {
return nil, errors.Wrap(err, "commit_transaction")
}
@@ -352,11 +363,11 @@ func (s SqlChannelStore) CreateSidebarCategory(userId, teamId string, newCategor
}
func (s SqlChannelStore) completePopulatingCategoryChannels(category *model.SidebarCategoryWithChannels) (*model.SidebarCategoryWithChannels, error) {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return nil, errors.Wrap(err, "begin_transaction")
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
result, err := s.completePopulatingCategoryChannelsT(transaction, category)
if err != nil {
@@ -399,7 +410,7 @@ func (s SqlChannelStore) completePopulatingCategoryChannelsT(db dbSelecter, cate
}).
Suffix(")")
var channels []string
channels := []string{}
sql, args, err := s.getQueryBuilder().
Select("Id").
From("ChannelMembers").
@@ -415,7 +426,7 @@ func (s SqlChannelStore) completePopulatingCategoryChannelsT(db dbSelecter, cate
return nil, errors.Wrap(err, "channel_tosql")
}
if _, err = db.Select(&channels, sql, args...); err != nil {
if err := db.Select(&channels, sql, args...); err != nil {
return nil, store.NewErrNotFound("ChannelMembers", "<too many fields>")
}
@@ -461,7 +472,7 @@ func (s SqlChannelStore) getSidebarCategoriesT(db dbSelecter, userId, teamId str
Order: make([]string, 0),
}
var categories []*sidebarCategoryForJoin
categories := []*sidebarCategoryForJoin{}
query, args, err := s.getQueryBuilder().
Select("SidebarCategories.*", "SidebarChannels.ChannelId").
From("SidebarCategories").
@@ -475,7 +486,7 @@ func (s SqlChannelStore) getSidebarCategoriesT(db dbSelecter, userId, teamId str
return nil, errors.Wrap(err, "sidebar_categories_tosql")
}
if _, err = db.Select(&categories, query, args...); err != nil {
if err := db.Select(&categories, query, args...); err != nil {
return nil, store.NewErrNotFound("SidebarCategories", fmt.Sprintf("userId=%s,teamId=%s", userId, teamId))
}
@@ -509,11 +520,11 @@ func (s SqlChannelStore) getSidebarCategoriesT(db dbSelecter, userId, teamId str
}
func (s SqlChannelStore) GetSidebarCategories(userId, teamId string) (*model.OrderedSidebarCategories, error) {
return s.getSidebarCategoriesT(s.GetReplica(), userId, teamId)
return s.getSidebarCategoriesT(s.GetReplicaX(), userId, teamId)
}
func (s SqlChannelStore) GetSidebarCategoryOrder(userId, teamId string) ([]string, error) {
var ids []string
ids := []string{}
sql, args, err := s.getQueryBuilder().
Select("Id").
@@ -528,43 +539,39 @@ func (s SqlChannelStore) GetSidebarCategoryOrder(userId, teamId string) ([]strin
return nil, errors.Wrap(err, "sidebar_category_tosql")
}
if _, err := s.GetReplica().Select(&ids, sql, args...); err != nil {
if err := s.GetReplicaX().Select(&ids, sql, args...); err != nil {
return nil, store.NewErrNotFound("SidebarCategories", fmt.Sprintf("userId=%s,teamId=%s", userId, teamId))
}
return ids, nil
}
func (s SqlChannelStore) updateSidebarCategoryOrderT(transaction *gorp.Transaction, categoryOrder []string) error {
var newOrder []interface{}
func (s SqlChannelStore) updateSidebarCategoryOrderT(transaction *sqlxTxWrapper, categoryOrder []string) error {
runningOrder := 0
for _, categoryId := range categoryOrder {
newOrder = append(newOrder, &model.SidebarCategory{
Id: categoryId,
SortOrder: int64(runningOrder),
})
sql, args, err := s.getQueryBuilder().
Update("SidebarCategories").
Set("SortOrder", runningOrder).
Where(sq.Eq{"Id": categoryId}).ToSql()
if err != nil {
return errors.Wrap(err, "updateSidebarCategoryOrderT_Tosql")
}
if _, err := transaction.Exec(sql, args...); err != nil {
return errors.Wrap(err, "Error updating sidebar category order")
}
runningOrder += model.MinimalSidebarSortDistance
}
// There's a bug in gorp where UpdateColumns messes up the stored query for any other attempt to use .Update or
// .UpdateColumns on this table, so it's okay to use here as long as we don't use those methods for SidebarCategories
// anywhere else.
if _, err := transaction.UpdateColumns(func(col *gorp.ColumnMap) bool {
return col.ColumnName == "SortOrder"
}, newOrder...); err != nil {
return errors.Wrap(err, "failed to update SidebarCategory")
}
return nil
}
func (s SqlChannelStore) UpdateSidebarCategoryOrder(userId, teamId string, categoryOrder []string) error {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return errors.Wrap(err, "begin_transaction")
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
// Ensure no invalid categories are included and that no categories are left out
existingOrder, err := s.GetSidebarCategoryOrder(userId, teamId)
@@ -589,11 +596,11 @@ func (s SqlChannelStore) UpdateSidebarCategoryOrder(userId, teamId string, categ
}
}
if err = s.updateSidebarCategoryOrderT(transaction, categoryOrder); err != nil {
if err := s.updateSidebarCategoryOrderT(transaction, categoryOrder); err != nil {
return err
}
if err = transaction.Commit(); err != nil {
if err := transaction.Commit(); err != nil {
return errors.Wrap(err, "commit_transaction")
}
@@ -602,11 +609,11 @@ func (s SqlChannelStore) UpdateSidebarCategoryOrder(userId, teamId string, categ
//nolint:unparam
func (s SqlChannelStore) UpdateSidebarCategories(userId, teamId string, categories []*model.SidebarCategoryWithChannels) ([]*model.SidebarCategoryWithChannels, []*model.SidebarCategoryWithChannels, error) {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return nil, nil, errors.Wrap(err, "begin_transaction")
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
updatedCategories := []*model.SidebarCategoryWithChannels{}
originalCategories := []*model.SidebarCategoryWithChannels{}
@@ -681,20 +688,24 @@ func (s SqlChannelStore) UpdateSidebarCategories(userId, teamId string, categori
return nil, nil, errors.Wrap(err, "failed to delete SidebarChannels")
}
var channels []interface{}
runningOrder := 0
insertQuery := s.getQueryBuilder().
Insert("SidebarChannels").
Columns("ChannelId", "UserId", "CategoryId", "SortOrder")
for _, channelID := range category.Channels {
channels = append(channels, &model.SidebarChannel{
ChannelId: channelID,
CategoryId: category.Id,
SortOrder: int64(runningOrder),
UserId: userId,
})
insertQuery = insertQuery.Values(channelID, userId, category.Id, int64(runningOrder))
runningOrder += model.MinimalSidebarSortDistance
}
if err = transaction.Insert(channels...); err != nil {
return nil, nil, errors.Wrap(err, "failed to save SidebarChannels")
if len(category.Channels) > 0 {
sql, args, err2 := insertQuery.ToSql()
if err2 != nil {
return nil, nil, errors.Wrap(err2, "InsertSidebarChannels_Tosql")
}
if _, err2 := transaction.Exec(sql, args...); err2 != nil {
return nil, nil, errors.Wrap(err2, "failed to save SidebarChannels")
}
}
}
@@ -768,11 +779,11 @@ func (s SqlChannelStore) UpdateSidebarCategories(userId, teamId string, categori
// UpdateSidebarChannelsByPreferences is called when the Preference table is being updated to keep SidebarCategories in sync
// At the moment, it's only handling Favorites and NOT DMs/GMs (those will be handled client side)
func (s SqlChannelStore) UpdateSidebarChannelsByPreferences(preferences model.Preferences) error {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return errors.Wrap(err, "UpdateSidebarChannelsByPreferences: begin_transaction")
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
for _, preference := range preferences {
preference := preference
@@ -800,18 +811,12 @@ func (s SqlChannelStore) UpdateSidebarChannelsByPreferences(preferences model.Pr
return nil
}
func (s SqlChannelStore) removeSidebarEntriesForPreferenceT(transaction *gorp.Transaction, preference *model.Preference) error {
func (s SqlChannelStore) removeSidebarEntriesForPreferenceT(transaction *sqlxTxWrapper, preference *model.Preference) error {
if preference.Category != model.PreferenceCategoryFavoriteChannel {
return nil
}
// Delete any corresponding SidebarChannels entries in a Favorites category corresponding to this preference. This
// can't use the query builder because it uses DB-specific syntax
params := map[string]interface{}{
"UserId": preference.UserId,
"ChannelId": preference.Name,
"CategoryType": model.SidebarCategoryFavorites,
}
// Delete any corresponding SidebarChannels entries in a Favorites category corresponding to this preference.
var query string
if s.DriverName() == model.DatabaseDriverMysql {
query = `
@@ -822,9 +827,9 @@ func (s SqlChannelStore) removeSidebarEntriesForPreferenceT(transaction *gorp.Tr
JOIN
SidebarCategories ON SidebarChannels.CategoryId = SidebarCategories.Id
WHERE
SidebarChannels.UserId = :UserId
AND SidebarChannels.ChannelId = :ChannelId
AND SidebarCategories.Type = :CategoryType`
SidebarChannels.UserId = ?
AND SidebarChannels.ChannelId = ?
AND SidebarCategories.Type = ?`
} else {
query = `
DELETE FROM
@@ -833,30 +838,28 @@ func (s SqlChannelStore) removeSidebarEntriesForPreferenceT(transaction *gorp.Tr
SidebarCategories
WHERE
SidebarChannels.CategoryId = SidebarCategories.Id
AND SidebarChannels.UserId = :UserId
AND SidebarChannels.ChannelId = :ChannelId
AND SidebarCategories.Type = :CategoryType`
AND SidebarChannels.UserId = ?
AND SidebarChannels.ChannelId = ?
AND SidebarCategories.Type = ?`
}
if _, err := transaction.Exec(query, params); err != nil {
if _, err := transaction.Exec(query, preference.UserId, preference.Name, model.SidebarCategoryFavorites); err != nil {
return errors.Wrap(err, "Failed to remove sidebar entries for preference")
}
return nil
}
func (s SqlChannelStore) addChannelToFavoritesCategoryT(transaction *gorp.Transaction, preference *model.Preference) error {
func (s SqlChannelStore) addChannelToFavoritesCategoryT(transaction *sqlxTxWrapper, preference *model.Preference) error {
if preference.Category != model.PreferenceCategoryFavoriteChannel {
return nil
}
var channel *model.Channel
if obj, err := transaction.Get(&model.Channel{}, preference.Name); err != nil {
var channel model.Channel
if err := transaction.Get(&channel, `SELECT * FROM Channels WHERE Id=?`, preference.Name); err != nil {
return errors.Wrapf(err, "Failed to get favorited channel with id=%s", preference.Name)
} else if obj == nil {
} else if channel.Id == "" {
return store.NewErrNotFound("Channel", preference.Name)
} else {
channel = obj.(*model.Channel)
}
// Get the IDs of the Favorites category/categories that the channel needs to be added to
@@ -876,8 +879,8 @@ func (s SqlChannelStore) addChannelToFavoritesCategoryT(transaction *gorp.Transa
idsQuery, idsParams, _ := builder.ToSql()
var categoryIds []string
if _, err := transaction.Select(&categoryIds, idsQuery, idsParams...); err != nil {
categoryIds := []string{}
if err := transaction.Select(&categoryIds, idsQuery, idsParams...); err != nil {
return errors.Wrap(err, "Failed to get Favorites sidebar categories")
}
@@ -919,11 +922,11 @@ func (s SqlChannelStore) addChannelToFavoritesCategoryT(transaction *gorp.Transa
// DeleteSidebarChannelsByPreferences is called when the Preference table is being updated to keep SidebarCategories in sync
// At the moment, it's only handling Favorites and NOT DMs/GMs (those will be handled client side)
func (s SqlChannelStore) DeleteSidebarChannelsByPreferences(preferences model.Preferences) error {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return errors.Wrap(err, "DeleteSidebarChannelsByPreferences: begin_transaction")
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
for _, preference := range preferences {
preference := preference
@@ -947,22 +950,17 @@ func (s SqlChannelStore) DeleteSidebarChannelsByPreferences(preferences model.Pr
//nolint:unparam
func (s SqlChannelStore) UpdateSidebarChannelCategoryOnMove(channel *model.Channel, newTeamId string) error {
// if channel is being moved, remove it from the categories, since it's possible that there's no matching category in the new team
if _, err := s.GetMaster().Exec("DELETE FROM SidebarChannels WHERE ChannelId=:ChannelId", map[string]interface{}{"ChannelId": channel.Id}); err != nil {
if _, err := s.GetMasterX().Exec("DELETE FROM SidebarChannels WHERE ChannelId=?", channel.Id); err != nil {
return errors.Wrapf(err, "failed to delete SidebarChannels with channelId=%s", channel.Id)
}
return nil
}
func (s SqlChannelStore) ClearSidebarOnTeamLeave(userId, teamId string) error {
// if user leaves the team, clean his team related entries in sidebar channels and categories
params := map[string]interface{}{
"UserId": userId,
"TeamId": teamId,
}
// if user leaves the team, clean their team related entries in sidebar channels and categories
var deleteQuery string
if s.DriverName() == model.DatabaseDriverMysql {
deleteQuery = "DELETE SidebarChannels FROM SidebarChannels LEFT JOIN SidebarCategories ON SidebarCategories.Id = SidebarChannels.CategoryId WHERE SidebarCategories.TeamId=:TeamId AND SidebarCategories.UserId=:UserId"
deleteQuery = "DELETE SidebarChannels FROM SidebarChannels LEFT JOIN SidebarCategories ON SidebarCategories.Id = SidebarChannels.CategoryId WHERE SidebarCategories.TeamId=? AND SidebarCategories.UserId=?"
} else {
deleteQuery = `
DELETE FROM
@@ -976,13 +974,13 @@ func (s SqlChannelStore) ClearSidebarOnTeamLeave(userId, teamId string) error {
SidebarCategories
WHERE
SidebarChannels.CategoryId = SidebarCategories.Id
AND SidebarCategories.TeamId = :TeamId
AND SidebarChannels.UserId = :UserId)`
AND SidebarCategories.TeamId = ?
AND SidebarChannels.UserId = ?)`
}
if _, err := s.GetMaster().Exec(deleteQuery, params); err != nil {
if _, err := s.GetMasterX().Exec(deleteQuery, teamId, userId); err != nil {
return errors.Wrap(err, "failed to delete from SidebarChannels")
}
if _, err := s.GetMaster().Exec("DELETE FROM SidebarCategories WHERE SidebarCategories.TeamId = :TeamId AND SidebarCategories.UserId = :UserId", params); err != nil {
if _, err := s.GetMasterX().Exec("DELETE FROM SidebarCategories WHERE SidebarCategories.TeamId = ? AND SidebarCategories.UserId = ?", teamId, userId); err != nil {
return errors.Wrap(err, "failed to delete from SidebarCategories")
}
return nil
@@ -991,15 +989,15 @@ func (s SqlChannelStore) ClearSidebarOnTeamLeave(userId, teamId string) error {
// DeleteSidebarCategory removes a custom category and moves any channels into it into the Channels and Direct Messages
// categories respectively. Assumes that the provided user ID and team ID match the given category ID.
func (s SqlChannelStore) DeleteSidebarCategory(categoryId string) error {
transaction, err := s.GetMaster().Begin()
transaction, err := s.GetMasterX().Beginx()
if err != nil {
return errors.Wrap(err, "begin_transaction")
}
defer finalizeTransaction(transaction)
defer finalizeTransactionX(transaction)
// Ensure that we're deleting a custom category
var category *model.SidebarCategory
if err = transaction.SelectOne(&category, "SELECT * FROM SidebarCategories WHERE Id = :Id", map[string]interface{}{"Id": categoryId}); err != nil {
var category model.SidebarCategory
if err = transaction.Get(&category, "SELECT * FROM SidebarCategories WHERE Id = ?", categoryId); err != nil {
return errors.Wrapf(err, "failed to find SidebarCategories with id=%s", categoryId)
}

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

@@ -5,11 +5,11 @@ package sqlstore
import (
sq "github.com/Masterminds/squirrel"
"github.com/mattermost/gorp"
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store"
"github.com/pkg/errors"
)
type SqlPreferenceStore struct {
@@ -67,7 +67,7 @@ func (s SqlPreferenceStore) Save(preferences model.Preferences) error {
return nil
}
func (s SqlPreferenceStore) save(transaction *gorp.Transaction, preference *model.Preference) error {
func (s SqlPreferenceStore) save(transaction *sqlxTxWrapper, preference *model.Preference) error {
preference.PreUpdate()
if err := preference.IsValid(); err != nil {

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

@@ -12,27 +12,18 @@ type dbSelecter struct {
}
// Select provides a mock function with given fields: i, query, args
func (_m *dbSelecter) Select(i interface{}, query string, args ...interface{}) ([]interface{}, error) {
func (_m *dbSelecter) Select(i interface{}, query string, args ...interface{}) error {
var _ca []interface{}
_ca = append(_ca, i, query)
_ca = append(_ca, args...)
ret := _m.Called(_ca...)
var r0 []interface{}
if rf, ok := ret.Get(0).(func(interface{}, string, ...interface{}) []interface{}); ok {
var r0 error
if rf, ok := ret.Get(0).(func(interface{}, string, ...interface{}) error); ok {
r0 = rf(i, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]interface{})
}
r0 = ret.Error(0)
}
var r1 error
if rf, ok := ret.Get(1).(func(interface{}, string, ...interface{}) error); ok {
r1 = rf(i, query, args...)
} else {
r1 = ret.Error(1)
}
return r0, r1
return r0
}