summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Hallam <jesse.hallam@gmail.com>2018-10-25 13:25:27 -0400
committerGitHub <noreply@github.com>2018-10-25 13:25:27 -0400
commit937b6480d534b3051cadf4a892a9aa210bec579a (patch)
tree7f8bcbde439f25cc9c0e405329ddf8a788208319
parent1074a1c7ab0769b0da3525282fcabf961e2ddfce (diff)
downloadchat-937b6480d534b3051cadf4a892a9aa210bec579a.zip
chat-937b6480d534b3051cadf4a892a9aa210bec579a.tar.gz
chat-937b6480d534b3051cadf4a892a9aa210bec579a.tar.bz2
MM-12342: merge the experimental channel store (#9681)HEADmaster
* MM-12342: merge the experimental channel store * gofmt after upgrading to go 1.11
-rw-r--r--app/app.go8
-rw-r--r--app/diagnostics.go17
-rw-r--r--config/default.json3
-rw-r--r--model/config.go25
-rw-r--r--store/sqlstore/channel_store.go390
-rw-r--r--store/sqlstore/channel_store_experimental.go778
-rw-r--r--store/sqlstore/supplier.go9
-rw-r--r--store/store.go4
-rw-r--r--store/storetest/channel_store.go105
-rw-r--r--store/storetest/mocks/ChannelStore.go38
10 files changed, 344 insertions, 1033 deletions
diff --git a/app/app.go b/app/app.go
index d8974a4..38756a9 100644
--- a/app/app.go
+++ b/app/app.go
@@ -219,14 +219,6 @@ func New(options ...Option) (outApp *App, outErr error) {
app.Srv.Store = app.newStore()
- app.AddConfigListener(func(_, current *model.Config) {
- if current.SqlSettings.EnablePublicChannelsMaterialization != nil && !*current.SqlSettings.EnablePublicChannelsMaterialization {
- app.Srv.Store.Channel().DisableExperimentalPublicChannelsMaterialization()
- } else {
- app.Srv.Store.Channel().EnableExperimentalPublicChannelsMaterialization()
- }
- })
-
if err := app.ensureAsymmetricSigningKey(); err != nil {
return nil, errors.Wrapf(err, "unable to ensure asymmetric signing key")
}
diff --git a/app/diagnostics.go b/app/diagnostics.go
index c9acc27..3c24a92 100644
--- a/app/diagnostics.go
+++ b/app/diagnostics.go
@@ -306,15 +306,14 @@ func (a *App) trackConfig() {
})
a.SendDiagnostic(TRACK_CONFIG_SQL, map[string]interface{}{
- "driver_name": *cfg.SqlSettings.DriverName,
- "trace": cfg.SqlSettings.Trace,
- "max_idle_conns": *cfg.SqlSettings.MaxIdleConns,
- "conn_max_lifetime_milliseconds": *cfg.SqlSettings.ConnMaxLifetimeMilliseconds,
- "max_open_conns": *cfg.SqlSettings.MaxOpenConns,
- "data_source_replicas": len(cfg.SqlSettings.DataSourceReplicas),
- "data_source_search_replicas": len(cfg.SqlSettings.DataSourceSearchReplicas),
- "query_timeout": *cfg.SqlSettings.QueryTimeout,
- "enable_public_channels_materialization": *cfg.SqlSettings.EnablePublicChannelsMaterialization,
+ "driver_name": *cfg.SqlSettings.DriverName,
+ "trace": cfg.SqlSettings.Trace,
+ "max_idle_conns": *cfg.SqlSettings.MaxIdleConns,
+ "conn_max_lifetime_milliseconds": *cfg.SqlSettings.ConnMaxLifetimeMilliseconds,
+ "max_open_conns": *cfg.SqlSettings.MaxOpenConns,
+ "data_source_replicas": len(cfg.SqlSettings.DataSourceReplicas),
+ "data_source_search_replicas": len(cfg.SqlSettings.DataSourceSearchReplicas),
+ "query_timeout": *cfg.SqlSettings.QueryTimeout,
})
a.SendDiagnostic(TRACK_CONFIG_LOG, map[string]interface{}{
diff --git a/config/default.json b/config/default.json
index 3daa6a3..6d428dd 100644
--- a/config/default.json
+++ b/config/default.json
@@ -133,8 +133,7 @@
"MaxOpenConns": 300,
"Trace": false,
"AtRestEncryptKey": "",
- "QueryTimeout": 30,
- "EnablePublicChannelsMaterialization": true
+ "QueryTimeout": 30
},
"LogSettings": {
"EnableConsole": true,
diff --git a/model/config.go b/model/config.go
index 6633c78..60e2574 100644
--- a/model/config.go
+++ b/model/config.go
@@ -683,17 +683,16 @@ type SSOSettings struct {
}
type SqlSettings struct {
- DriverName *string
- DataSource *string
- DataSourceReplicas []string
- DataSourceSearchReplicas []string
- MaxIdleConns *int
- ConnMaxLifetimeMilliseconds *int
- MaxOpenConns *int
- Trace bool
- AtRestEncryptKey string
- QueryTimeout *int
- EnablePublicChannelsMaterialization *bool
+ DriverName *string
+ DataSource *string
+ DataSourceReplicas []string
+ DataSourceSearchReplicas []string
+ MaxIdleConns *int
+ ConnMaxLifetimeMilliseconds *int
+ MaxOpenConns *int
+ Trace bool
+ AtRestEncryptKey string
+ QueryTimeout *int
}
func (s *SqlSettings) SetDefaults() {
@@ -724,10 +723,6 @@ func (s *SqlSettings) SetDefaults() {
if s.QueryTimeout == nil {
s.QueryTimeout = NewInt(30)
}
-
- if s.EnablePublicChannelsMaterialization == nil {
- s.EnablePublicChannelsMaterialization = NewBool(true)
- }
}
type LogSettings struct {
diff --git a/store/sqlstore/channel_store.go b/store/sqlstore/channel_store.go
index 63b9fbb..5947a8f 100644
--- a/store/sqlstore/channel_store.go
+++ b/store/sqlstore/channel_store.go
@@ -12,6 +12,7 @@ import (
"strings"
"github.com/mattermost/gorp"
+ "github.com/pkg/errors"
"github.com/mattermost/mattermost-server/einterfaces"
"github.com/mattermost/mattermost-server/mlog"
@@ -232,6 +233,17 @@ func (db allChannelMembers) ToMapStringString() map[string]string {
return result
}
+// publicChannel is a subset of the metadata corresponding to public channels only.
+type publicChannel struct {
+ Id string `json:"id"`
+ DeleteAt int64 `json:"delete_at"`
+ TeamId string `json:"team_id"`
+ DisplayName string `json:"display_name"`
+ Name string `json:"name"`
+ Header string `json:"header"`
+ Purpose string `json:"purpose"`
+}
+
var channelMemberCountsCache = utils.NewLru(CHANNEL_MEMBERS_COUNTS_CACHE_SIZE)
var allChannelMembersForUserCache = utils.NewLru(ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE)
var allChannelMembersNotifyPropsForChannelCache = utils.NewLru(ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE)
@@ -278,6 +290,15 @@ func NewSqlChannelStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface)
tablem.ColMap("UserId").SetMaxSize(26)
tablem.ColMap("Roles").SetMaxSize(64)
tablem.ColMap("NotifyProps").SetMaxSize(2000)
+
+ tablePublicChannels := db.AddTableWithName(publicChannel{}, "PublicChannels").SetKeys(false, "Id")
+ tablePublicChannels.ColMap("Id").SetMaxSize(26)
+ tablePublicChannels.ColMap("TeamId").SetMaxSize(26)
+ tablePublicChannels.ColMap("DisplayName").SetMaxSize(64)
+ tablePublicChannels.ColMap("Name").SetMaxSize(64)
+ tablePublicChannels.SetUniqueTogether("Name", "TeamId")
+ tablePublicChannels.ColMap("Header").SetMaxSize(1024)
+ tablePublicChannels.ColMap("Purpose").SetMaxSize(250)
}
return s
@@ -299,21 +320,112 @@ func (s SqlChannelStore) CreateIndexesIfNotExists() {
s.CreateIndexIfNotExists("idx_channelmembers_user_id", "ChannelMembers", "UserId")
s.CreateFullTextIndexIfNotExists("idx_channel_search_txt", "Channels", "Name, DisplayName, Purpose")
+
+ s.CreateIndexIfNotExists("idx_publicchannels_team_id", "PublicChannels", "TeamId")
+ s.CreateIndexIfNotExists("idx_publicchannels_name", "PublicChannels", "Name")
+ s.CreateIndexIfNotExists("idx_publicchannels_delete_at", "PublicChannels", "DeleteAt")
+ if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
+ s.CreateIndexIfNotExists("idx_publicchannels_name_lower", "PublicChannels", "lower(Name)")
+ s.CreateIndexIfNotExists("idx_publicchannels_displayname_lower", "PublicChannels", "lower(DisplayName)")
+ }
+ s.CreateFullTextIndexIfNotExists("idx_publicchannels_search_txt", "PublicChannels", "Name, DisplayName, Purpose")
}
+// MigratePublicChannels initializes the PublicChannels table with data created before this version
+// of the Mattermost server kept it up-to-date.
func (s SqlChannelStore) MigratePublicChannels() error {
- // See SqlChannelStoreExperimental
+ transaction, err := s.GetMaster().Begin()
+ if err != nil {
+ return err
+ }
+
+ if _, err := transaction.Exec(`
+ INSERT INTO PublicChannels
+ (Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
+ SELECT
+ c.Id, c.DeleteAt, c.TeamId, c.DisplayName, c.Name, c.Header, c.Purpose
+ FROM
+ Channels c
+ LEFT JOIN
+ PublicChannels pc ON (pc.Id = c.Id)
+ WHERE
+ c.Type = 'O'
+ AND pc.Id IS NULL
+ `); err != nil {
+ return err
+ }
+
+ if err := transaction.Commit(); err != nil {
+ return err
+ }
+
return nil
}
-func (s SqlChannelStore) DropPublicChannels() error {
- // See SqlChannelStoreExperimental
+func (s SqlChannelStore) upsertPublicChannelT(transaction *gorp.Transaction, channel *model.Channel) error {
+ publicChannel := &publicChannel{
+ Id: channel.Id,
+ DeleteAt: channel.DeleteAt,
+ TeamId: channel.TeamId,
+ DisplayName: channel.DisplayName,
+ Name: channel.Name,
+ Header: channel.Header,
+ Purpose: channel.Purpose,
+ }
+
+ if channel.Type != model.CHANNEL_OPEN {
+ if _, err := transaction.Delete(publicChannel); err != nil {
+ return errors.Wrap(err, "failed to delete public channel")
+ }
+
+ return nil
+ }
+
+ if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
+ // Leverage native upsert for MySQL, since RowsAffected returns 0 if the row exists
+ // but no changes were made, breaking the update-then-insert paradigm below when
+ // the row already exists. (Postgres 9.4 doesn't support native upsert.)
+ if _, err := transaction.Exec(`
+ INSERT INTO
+ PublicChannels(Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
+ VALUES
+ (:Id, :DeleteAt, :TeamId, :DisplayName, :Name, :Header, :Purpose)
+ ON DUPLICATE KEY UPDATE
+ DeleteAt = :DeleteAt,
+ TeamId = :TeamId,
+ DisplayName = :DisplayName,
+ Name = :Name,
+ Header = :Header,
+ Purpose = :Purpose;
+ `, map[string]interface{}{
+ "Id": publicChannel.Id,
+ "DeleteAt": publicChannel.DeleteAt,
+ "TeamId": publicChannel.TeamId,
+ "DisplayName": publicChannel.DisplayName,
+ "Name": publicChannel.Name,
+ "Header": publicChannel.Header,
+ "Purpose": publicChannel.Purpose,
+ }); err != nil {
+ return errors.Wrap(err, "failed to insert public channel")
+ }
+ } else {
+ count, err := transaction.Update(publicChannel)
+ if err != nil {
+ return errors.Wrap(err, "failed to update public channel")
+ }
+ if count > 0 {
+ return nil
+ }
+
+ if err := transaction.Insert(publicChannel); err != nil {
+ return errors.Wrap(err, "failed to insert public channel")
+ }
+ }
+
return nil
}
// Save writes the (non-direct) channel channel to the database.
-//
-// @see ChannelStoreExperimental for how this update propagates to the PublicChannels table.
func (s SqlChannelStore) Save(channel *model.Channel, maxChannelsPerTeam int64) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
if channel.DeleteAt != 0 {
@@ -338,6 +450,13 @@ func (s SqlChannelStore) Save(channel *model.Channel, maxChannelsPerTeam int64)
return
}
+ // Additionally propagate the write to the PublicChannels table.
+ if err := s.upsertPublicChannelT(transaction, result.Data.(*model.Channel)); err != nil {
+ transaction.Rollback()
+ result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.upsert_public_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
if err := transaction.Commit(); err != nil {
result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
return
@@ -473,8 +592,6 @@ func (s SqlChannelStore) saveChannelT(transaction *gorp.Transaction, channel *mo
}
// Update writes the updated channel to the database.
-//
-// @see ChannelStoreExperimental for how this update propagates to the PublicChannels table.
func (s SqlChannelStore) Update(channel *model.Channel) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
transaction, err := s.GetMaster().Begin()
@@ -489,11 +606,19 @@ func (s SqlChannelStore) Update(channel *model.Channel) store.StoreChannel {
return
}
+ // Additionally propagate the write to the PublicChannels table.
+ if err := s.upsertPublicChannelT(transaction, result.Data.(*model.Channel)); err != nil {
+ transaction.Rollback()
+ result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.upsert_public_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
if err := transaction.Commit(); err != nil {
result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
})
+
}
func (s SqlChannelStore) updateChannelT(transaction *gorp.Transaction, channel *model.Channel) store.StoreResult {
@@ -642,22 +767,16 @@ func (s SqlChannelStore) get(id string, master bool, allowFromCache bool) store.
}
// Delete records the given deleted timestamp to the channel in question.
-//
-// @see ChannelStoreExperimental for how this update propagates to the PublicChannels table.
func (s SqlChannelStore) Delete(channelId string, time int64) store.StoreChannel {
return s.SetDeleteAt(channelId, time, time)
}
// Restore reverts a previous deleted timestamp from the channel in question.
-//
-// @see ChannelStoreExperimental for how this update propagates to the PublicChannels table.
func (s SqlChannelStore) Restore(channelId string, time int64) store.StoreChannel {
return s.SetDeleteAt(channelId, 0, time)
}
// SetDeleteAt records the given deleted and updated timestamp to the channel in question.
-//
-// @see ChannelStoreExperimental for how this update propagates to the PublicChannels table.
func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
defer s.InvalidateChannel(channelId)
@@ -674,6 +793,23 @@ func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64)
return
}
+ // Additionally propagate the write to the PublicChannels table.
+ if _, err := transaction.Exec(`
+ UPDATE
+ PublicChannels
+ SET
+ DeleteAt = :DeleteAt
+ WHERE
+ Id = :ChannelId
+ `, map[string]interface{}{
+ "DeleteAt": deleteAt,
+ "ChannelId": channelId,
+ }); err != nil {
+ transaction.Rollback()
+ result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.update_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
if err := transaction.Commit(); err != nil {
result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
return
@@ -694,8 +830,6 @@ func (s SqlChannelStore) setDeleteAtT(transaction *gorp.Transaction, channelId s
}
// PermanentDeleteByTeam removes all channels for the given team from the database.
-//
-// @see ChannelStoreExperimental for how this update propagates to the PublicChannels table.
func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
transaction, err := s.GetMaster().Begin()
@@ -710,6 +844,20 @@ func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) store.StoreChannel
return
}
+ // Additionally propagate the deletions to the PublicChannels table.
+ if _, err := transaction.Exec(`
+ DELETE FROM
+ PublicChannels
+ WHERE
+ TeamId = :TeamId
+ `, map[string]interface{}{
+ "TeamId": teamId,
+ }); err != nil {
+ transaction.Rollback()
+ result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeamt", "store.sql_channel.permanent_delete_by_team.delete_public_channels.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
if err := transaction.Commit(); err != nil {
result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
return
@@ -729,8 +877,6 @@ func (s SqlChannelStore) permanentDeleteByTeamtT(transaction *gorp.Transaction,
}
// PermanentDelete removes the given channel from the database.
-//
-// @see ChannelStoreExperimental for how this update propagates to the PublicChannels table.
func (s SqlChannelStore) PermanentDelete(channelId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
transaction, err := s.GetMaster().Begin()
@@ -745,6 +891,20 @@ func (s SqlChannelStore) PermanentDelete(channelId string) store.StoreChannel {
return
}
+ // Additionally propagate the deletion to the PublicChannels table.
+ if _, err := transaction.Exec(`
+ DELETE FROM
+ PublicChannels
+ WHERE
+ Id = :ChannelId
+ `, map[string]interface{}{
+ "ChannelId": channelId,
+ }); err != nil {
+ transaction.Rollback()
+ result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.delete_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
+ return
+ }
+
if err := transaction.Commit(); err != nil {
result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
return
@@ -798,29 +958,38 @@ func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDelete
func (s SqlChannelStore) GetMoreChannels(teamId string, userId string, offset int, limit int) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
data := &model.ChannelList{}
- _, err := s.GetReplica().Select(data,
- `SELECT
- *
+ _, err := s.GetReplica().Select(data, `
+ SELECT
+ Channels.*
FROM
Channels
+ JOIN
+ PublicChannels c ON (c.Id = Channels.Id)
WHERE
- TeamId = :TeamId1
- AND Type IN ('O')
- AND DeleteAt = 0
- AND Id NOT IN (SELECT
- Channels.Id
- FROM
- Channels,
- ChannelMembers
- WHERE
- Id = ChannelId
- AND TeamId = :TeamId2
- AND UserId = :UserId
- AND DeleteAt = 0)
- ORDER BY DisplayName
+ c.TeamId = :TeamId
+ AND c.DeleteAt = 0
+ AND c.Id NOT IN (
+ SELECT
+ c.Id
+ FROM
+ PublicChannels c
+ JOIN
+ ChannelMembers cm ON (cm.ChannelId = c.Id)
+ WHERE
+ c.TeamId = :TeamId
+ AND cm.UserId = :UserId
+ AND c.DeleteAt = 0
+ )
+ ORDER BY
+ c.DisplayName
LIMIT :Limit
- OFFSET :Offset`,
- map[string]interface{}{"TeamId1": teamId, "TeamId2": teamId, "UserId": userId, "Limit": limit, "Offset": offset})
+ OFFSET :Offset
+ `, map[string]interface{}{
+ "TeamId": teamId,
+ "UserId": userId,
+ "Limit": limit,
+ "Offset": offset,
+ })
if err != nil {
result.Err = model.NewAppError("SqlChannelStore.GetMoreChannels", "store.sql_channel.get_more_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
@@ -834,19 +1003,24 @@ func (s SqlChannelStore) GetMoreChannels(teamId string, userId string, offset in
func (s SqlChannelStore) GetPublicChannelsForTeam(teamId string, offset int, limit int) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
data := &model.ChannelList{}
- _, err := s.GetReplica().Select(data,
- `SELECT
- *
+ _, err := s.GetReplica().Select(data, `
+ SELECT
+ Channels.*
FROM
Channels
+ JOIN
+ PublicChannels pc ON (pc.Id = Channels.Id)
WHERE
- TeamId = :TeamId
- AND Type = 'O'
- AND DeleteAt = 0
- ORDER BY DisplayName
+ pc.TeamId = :TeamId
+ AND pc.DeleteAt = 0
+ ORDER BY pc.DisplayName
LIMIT :Limit
- OFFSET :Offset`,
- map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset})
+ OFFSET :Offset
+ `, map[string]interface{}{
+ "TeamId": teamId,
+ "Limit": limit,
+ "Offset": offset,
+ })
if err != nil {
result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsForTeam", "store.sql_channel.get_public_channels.get.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError)
@@ -874,18 +1048,19 @@ func (s SqlChannelStore) GetPublicChannelsByIdsForTeam(teamId string, channelIds
}
data := &model.ChannelList{}
- _, err := s.GetReplica().Select(data,
- `SELECT
- *
+ _, err := s.GetReplica().Select(data, `
+ SELECT
+ Channels.*
FROM
Channels
+ JOIN
+ PublicChannels pc ON (pc.Id = Channels.Id)
WHERE
- TeamId = :teamId
- AND Type = 'O'
- AND DeleteAt = 0
- AND Id IN (`+idQuery+`)
- ORDER BY DisplayName`,
- props)
+ pc.TeamId = :teamId
+ AND pc.DeleteAt = 0
+ AND pc.Id IN (`+idQuery+`)
+ ORDER BY pc.DisplayName
+ `, props)
if err != nil {
result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.get.app_error", nil, err.Error(), http.StatusInternalServerError)
@@ -1721,33 +1896,35 @@ func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) store.S
func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
- deleteFilter := "AND DeleteAt = 0"
+ deleteFilter := "AND c.DeleteAt = 0"
if includeDeleted {
deleteFilter = ""
}
queryFormat := `
SELECT
- *
+ Channels.*
FROM
- Channels
+ Channels
+ JOIN
+ PublicChannels c ON (c.Id = Channels.Id)
WHERE
- TeamId = :TeamId
- AND Type = 'O'
- ` + deleteFilter + `
- %v
- LIMIT 50`
+ c.TeamId = :TeamId
+ ` + deleteFilter + `
+ %v
+ LIMIT 50
+ `
var channels model.ChannelList
- if likeClause, likeTerm := s.buildLIKEClause(term, "Name, DisplayName, Purpose"); likeClause == "" {
+ if likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose"); likeClause == "" {
if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil {
result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
}
} else {
// Using a UNION results in index_merge and fulltext queries and is much faster than the ref
// query you would get using an OR of the LIKE and full-text clauses.
- fulltextClause, fulltextTerm := s.buildFulltextClause(term, "Name, DisplayName, Purpose")
+ fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
@@ -1863,53 +2040,61 @@ func (s SqlChannelStore) autocompleteInTeamForSearchDirectMessages(userId string
func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
- deleteFilter := "AND DeleteAt = 0"
+ deleteFilter := "AND c.DeleteAt = 0"
if includeDeleted {
deleteFilter = ""
}
- searchQuery := `
+
+ *result = s.performSearch(`
SELECT
- *
+ Channels.*
FROM
- Channels
+ Channels
+ JOIN
+ PublicChannels c ON (c.Id = Channels.Id)
WHERE
- TeamId = :TeamId
- AND Type = 'O'
- ` + deleteFilter + `
- SEARCH_CLAUSE
- ORDER BY DisplayName
- LIMIT 100`
-
- *result = s.performSearch(searchQuery, term, map[string]interface{}{"TeamId": teamId})
+ c.TeamId = :TeamId
+ `+deleteFilter+`
+ SEARCH_CLAUSE
+ ORDER BY c.DisplayName
+ LIMIT 100
+ `, term, map[string]interface{}{
+ "TeamId": teamId,
+ })
})
}
func (s SqlChannelStore) SearchMore(userId string, teamId string, term string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
- searchQuery := `
+ *result = s.performSearch(`
SELECT
- *
+ Channels.*
FROM
Channels
+ JOIN
+ PublicChannels c ON (c.Id = Channels.Id)
WHERE
- TeamId = :TeamId
- AND Type = 'O'
- AND DeleteAt = 0
- AND Id NOT IN (SELECT
- Channels.Id
+ c.TeamId = :TeamId
+ AND c.DeleteAt = 0
+ AND c.Id NOT IN (
+ SELECT
+ c.Id
FROM
- Channels,
- ChannelMembers
+ PublicChannels c
+ JOIN
+ ChannelMembers cm ON (cm.ChannelId = c.Id)
WHERE
- Id = ChannelId
- AND TeamId = :TeamId
- AND UserId = :UserId
- AND DeleteAt = 0)
- SEARCH_CLAUSE
- ORDER BY DisplayName
- LIMIT 100`
-
- *result = s.performSearch(searchQuery, term, map[string]interface{}{"TeamId": teamId, "UserId": userId})
+ c.TeamId = :TeamId
+ AND cm.UserId = :UserId
+ AND c.DeleteAt = 0
+ )
+ SEARCH_CLAUSE
+ ORDER BY c.DisplayName
+ LIMIT 100
+ `, term, map[string]interface{}{
+ "TeamId": teamId,
+ "UserId": userId,
+ })
})
}
@@ -1987,13 +2172,13 @@ func (s SqlChannelStore) buildFulltextClause(term string, searchColumns string)
func (s SqlChannelStore) performSearch(searchQuery string, term string, parameters map[string]interface{}) store.StoreResult {
result := store.StoreResult{}
- likeClause, likeTerm := s.buildLIKEClause(term, "Name, DisplayName, Purpose")
+ likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
if likeTerm == "" {
// If the likeTerm is empty after preparing, then don't bother searching.
searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1)
} else {
parameters["LikeTerm"] = likeTerm
- fulltextClause, fulltextTerm := s.buildFulltextClause(term, "Name, DisplayName, Purpose")
+ fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
parameters["FulltextTerm"] = fulltextTerm
searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1)
}
@@ -2259,19 +2444,6 @@ func (s SqlChannelStore) resetLastPostAtT(transaction *gorp.Transaction) store.S
return result
}
-func (s SqlChannelStore) EnableExperimentalPublicChannelsMaterialization() {
- // See SqlChannelStoreExperimental
-}
-
-func (s SqlChannelStore) DisableExperimentalPublicChannelsMaterialization() {
- // See SqlChannelStoreExperimental
-}
-
-func (s SqlChannelStore) IsExperimentalPublicChannelsMaterializationEnabled() bool {
- // See SqlChannelStoreExperimental
- return false
-}
-
func (s SqlChannelStore) GetAllChannelsForExportAfter(limit int, afterId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
var data []*model.ChannelForExport
diff --git a/store/sqlstore/channel_store_experimental.go b/store/sqlstore/channel_store_experimental.go
deleted file mode 100644
index ed1b4c0..0000000
--- a/store/sqlstore/channel_store_experimental.go
+++ /dev/null
@@ -1,778 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-package sqlstore
-
-import (
- "fmt"
- "net/http"
- "sort"
- "strconv"
- "strings"
- "sync/atomic"
-
- "github.com/pkg/errors"
-
- "github.com/mattermost/gorp"
- "github.com/mattermost/mattermost-server/einterfaces"
- "github.com/mattermost/mattermost-server/mlog"
- "github.com/mattermost/mattermost-server/model"
- "github.com/mattermost/mattermost-server/store"
-)
-
-// publicChannel is a subset of the metadata corresponding to public channels only.
-type publicChannel struct {
- Id string `json:"id"`
- DeleteAt int64 `json:"delete_at"`
- TeamId string `json:"team_id"`
- DisplayName string `json:"display_name"`
- Name string `json:"name"`
- Header string `json:"header"`
- Purpose string `json:"purpose"`
-}
-
-type SqlChannelStoreExperimental struct {
- SqlChannelStore
- experimentalPublicChannelsMaterializationDisabled *uint32
-}
-
-func NewSqlChannelStoreExperimental(sqlStore SqlStore, metrics einterfaces.MetricsInterface, enabled bool) store.ChannelStore {
- s := &SqlChannelStoreExperimental{
- SqlChannelStore: *NewSqlChannelStore(sqlStore, metrics).(*SqlChannelStore),
- experimentalPublicChannelsMaterializationDisabled: new(uint32),
- }
-
- if enabled {
- // Forcibly log, since the default state is enabled and we want this on startup.
- mlog.Info("Enabling experimental public channels materialization")
- s.EnableExperimentalPublicChannelsMaterialization()
- } else {
- s.DisableExperimentalPublicChannelsMaterialization()
- }
-
- if s.IsExperimentalPublicChannelsMaterializationEnabled() {
- for _, db := range sqlStore.GetAllConns() {
- tablePublicChannels := db.AddTableWithName(publicChannel{}, "PublicChannels").SetKeys(false, "Id")
- tablePublicChannels.ColMap("Id").SetMaxSize(26)
- tablePublicChannels.ColMap("TeamId").SetMaxSize(26)
- tablePublicChannels.ColMap("DisplayName").SetMaxSize(64)
- tablePublicChannels.ColMap("Name").SetMaxSize(64)
- tablePublicChannels.SetUniqueTogether("Name", "TeamId")
- tablePublicChannels.ColMap("Header").SetMaxSize(1024)
- tablePublicChannels.ColMap("Purpose").SetMaxSize(250)
- }
- }
-
- return s
-}
-
-// migratePublicChannels initializes the PublicChannels table with data created before this version
-// of the Mattermost server kept it up-to-date.
-func (s SqlChannelStoreExperimental) MigratePublicChannels() error {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.MigratePublicChannels()
- }
-
- transaction, err := s.GetMaster().Begin()
- if err != nil {
- return err
- }
-
- if _, err := transaction.Exec(`
- INSERT INTO PublicChannels
- (Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
- SELECT
- c.Id, c.DeleteAt, c.TeamId, c.DisplayName, c.Name, c.Header, c.Purpose
- FROM
- Channels c
- LEFT JOIN
- PublicChannels pc ON (pc.Id = c.Id)
- WHERE
- c.Type = 'O'
- AND pc.Id IS NULL
- `); err != nil {
- return err
- }
-
- if err := transaction.Commit(); err != nil {
- return err
- }
-
- return nil
-}
-
-// DropPublicChannels removes the public channels table.
-func (s SqlChannelStoreExperimental) DropPublicChannels() error {
- _, err := s.GetMaster().Exec(`
- DROP TABLE IF EXISTS PublicChannels
- `)
- if err != nil {
- return errors.Wrap(err, "failed to drop public channels table")
- }
-
- return nil
-}
-
-func (s SqlChannelStoreExperimental) CreateIndexesIfNotExists() {
- s.SqlChannelStore.CreateIndexesIfNotExists()
-
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return
- }
-
- s.CreateIndexIfNotExists("idx_publicchannels_team_id", "PublicChannels", "TeamId")
- s.CreateIndexIfNotExists("idx_publicchannels_name", "PublicChannels", "Name")
- s.CreateIndexIfNotExists("idx_publicchannels_delete_at", "PublicChannels", "DeleteAt")
- if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
- s.CreateIndexIfNotExists("idx_publicchannels_name_lower", "PublicChannels", "lower(Name)")
- s.CreateIndexIfNotExists("idx_publicchannels_displayname_lower", "PublicChannels", "lower(DisplayName)")
- }
- s.CreateFullTextIndexIfNotExists("idx_publicchannels_search_txt", "PublicChannels", "Name, DisplayName, Purpose")
-}
-
-func (s SqlChannelStoreExperimental) upsertPublicChannelT(transaction *gorp.Transaction, channel *model.Channel) error {
- publicChannel := &publicChannel{
- Id: channel.Id,
- DeleteAt: channel.DeleteAt,
- TeamId: channel.TeamId,
- DisplayName: channel.DisplayName,
- Name: channel.Name,
- Header: channel.Header,
- Purpose: channel.Purpose,
- }
-
- if channel.Type != model.CHANNEL_OPEN {
- if _, err := transaction.Delete(publicChannel); err != nil {
- return errors.Wrap(err, "failed to delete public channel")
- }
-
- return nil
- }
-
- if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
- // Leverage native upsert for MySQL, since RowsAffected returns 0 if the row exists
- // but no changes were made, breaking the update-then-insert paradigm below when
- // the row already exists. (Postgres 9.4 doesn't support native upsert.)
- if _, err := transaction.Exec(`
- INSERT INTO
- PublicChannels(Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
- VALUES
- (:Id, :DeleteAt, :TeamId, :DisplayName, :Name, :Header, :Purpose)
- ON DUPLICATE KEY UPDATE
- DeleteAt = :DeleteAt,
- TeamId = :TeamId,
- DisplayName = :DisplayName,
- Name = :Name,
- Header = :Header,
- Purpose = :Purpose;
- `, map[string]interface{}{
- "Id": publicChannel.Id,
- "DeleteAt": publicChannel.DeleteAt,
- "TeamId": publicChannel.TeamId,
- "DisplayName": publicChannel.DisplayName,
- "Name": publicChannel.Name,
- "Header": publicChannel.Header,
- "Purpose": publicChannel.Purpose,
- }); err != nil {
- return errors.Wrap(err, "failed to insert public channel")
- }
- } else {
- count, err := transaction.Update(publicChannel)
- if err != nil {
- return errors.Wrap(err, "failed to update public channel")
- }
- if count > 0 {
- return nil
- }
-
- if err := transaction.Insert(publicChannel); err != nil {
- return errors.Wrap(err, "failed to insert public channel")
- }
- }
-
- return nil
-}
-
-func (s SqlChannelStoreExperimental) Save(channel *model.Channel, maxChannelsPerTeam int64) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.Save(channel, maxChannelsPerTeam)
- }
-
- return store.Do(func(result *store.StoreResult) {
- if channel.DeleteAt != 0 {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest)
- return
- }
-
- if channel.Type == model.CHANNEL_DIRECT {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.Save", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest)
- return
- }
-
- transaction, err := s.GetMaster().Begin()
- if err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.Save", "store.sql_channel.save.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
-
- *result = s.saveChannelT(transaction, channel, maxChannelsPerTeam)
- if result.Err != nil {
- transaction.Rollback()
- return
- }
-
- // Additionally propagate the write to the PublicChannels table.
- if err := s.upsertPublicChannelT(transaction, result.Data.(*model.Channel)); err != nil {
- transaction.Rollback()
- result.Err = model.NewAppError("SqlChannelStoreExperimental.Save", "store.sql_channel.save.upsert_public_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
-
- if err := transaction.Commit(); err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.Save", "store.sql_channel.save.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
- })
-}
-
-func (s SqlChannelStoreExperimental) Update(channel *model.Channel) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.Update(channel)
- }
-
- return store.Do(func(result *store.StoreResult) {
- transaction, err := s.GetMaster().Begin()
- if err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.Update", "store.sql_channel.update.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
-
- *result = s.updateChannelT(transaction, channel)
- if result.Err != nil {
- transaction.Rollback()
- return
- }
-
- // Additionally propagate the write to the PublicChannels table.
- if err := s.upsertPublicChannelT(transaction, result.Data.(*model.Channel)); err != nil {
- transaction.Rollback()
- result.Err = model.NewAppError("SqlChannelStoreExperimental.Update", "store.sql_channel.update.upsert_public_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
-
- if err := transaction.Commit(); err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.Update", "store.sql_channel.update.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
- })
-}
-
-func (s SqlChannelStoreExperimental) Delete(channelId string, time int64) store.StoreChannel {
- // Call the experimental version first.
- return s.SetDeleteAt(channelId, time, time)
-}
-
-func (s SqlChannelStoreExperimental) Restore(channelId string, time int64) store.StoreChannel {
- // Call the experimental version first.
- return s.SetDeleteAt(channelId, 0, time)
-}
-
-func (s SqlChannelStoreExperimental) SetDeleteAt(channelId string, deleteAt, updateAt int64) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.SetDeleteAt(channelId, deleteAt, updateAt)
- }
-
- return store.Do(func(result *store.StoreResult) {
- defer s.InvalidateChannel(channelId)
-
- transaction, err := s.GetMaster().Begin()
- if err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.SetDeleteAt", "store.sql_channel.set_delete_at.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
-
- *result = s.setDeleteAtT(transaction, channelId, deleteAt, updateAt)
- if result.Err != nil {
- transaction.Rollback()
- return
- }
-
- // Additionally propagate the write to the PublicChannels table.
- if _, err := transaction.Exec(`
- UPDATE
- PublicChannels
- SET
- DeleteAt = :DeleteAt
- WHERE
- Id = :ChannelId
- `, map[string]interface{}{
- "DeleteAt": deleteAt,
- "ChannelId": channelId,
- }); err != nil {
- transaction.Rollback()
- result.Err = model.NewAppError("SqlChannelStoreExperimental.SetDeleteAt", "store.sql_channel.set_delete_at.update_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
- return
- }
-
- if err := transaction.Commit(); err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.SetDeleteAt", "store.sql_channel.set_delete_at.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
- })
-}
-
-func (s SqlChannelStoreExperimental) PermanentDeleteByTeam(teamId string) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.PermanentDeleteByTeam(teamId)
- }
-
- return store.Do(func(result *store.StoreResult) {
- transaction, err := s.GetMaster().Begin()
- if err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
-
- *result = s.permanentDeleteByTeamtT(transaction, teamId)
- if result.Err != nil {
- transaction.Rollback()
- return
- }
-
- // Additionally propagate the deletions to the PublicChannels table.
- if _, err := transaction.Exec(`
- DELETE FROM
- PublicChannels
- WHERE
- TeamId = :TeamId
- `, map[string]interface{}{
- "TeamId": teamId,
- }); err != nil {
- transaction.Rollback()
- result.Err = model.NewAppError("SqlChannelStoreExperimental.PermanentDeleteByTeamt", "store.sql_channel.permanent_delete_by_team.delete_public_channels.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError)
- return
- }
-
- if err := transaction.Commit(); err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
- })
-}
-
-func (s SqlChannelStoreExperimental) PermanentDelete(channelId string) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.PermanentDelete(channelId)
- }
-
- return store.Do(func(result *store.StoreResult) {
- transaction, err := s.GetMaster().Begin()
- if err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.PermanentDelete", "store.sql_channel.permanent_delete.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
-
- *result = s.permanentDeleteT(transaction, channelId)
- if result.Err != nil {
- transaction.Rollback()
- return
- }
-
- // Additionally propagate the deletion to the PublicChannels table.
- if _, err := transaction.Exec(`
- DELETE FROM
- PublicChannels
- WHERE
- Id = :ChannelId
- `, map[string]interface{}{
- "ChannelId": channelId,
- }); err != nil {
- transaction.Rollback()
- result.Err = model.NewAppError("SqlChannelStoreExperimental.PermanentDelete", "store.sql_channel.permanent_delete.delete_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
- return
- }
-
- if err := transaction.Commit(); err != nil {
- result.Err = model.NewAppError("SqlChannelStoreExperimental.PermanentDelete", "store.sql_channel.permanent_delete.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
- return
- }
- })
-}
-
-func (s SqlChannelStoreExperimental) GetMoreChannels(teamId string, userId string, offset int, limit int) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.GetMoreChannels(teamId, userId, offset, limit)
- }
-
- return store.Do(func(result *store.StoreResult) {
- data := &model.ChannelList{}
- _, err := s.GetReplica().Select(data, `
- SELECT
- Channels.*
- FROM
- Channels
- JOIN
- PublicChannels c ON (c.Id = Channels.Id)
- WHERE
- c.TeamId = :TeamId
- AND c.DeleteAt = 0
- AND c.Id NOT IN (
- SELECT
- c.Id
- FROM
- PublicChannels c
- JOIN
- ChannelMembers cm ON (cm.ChannelId = c.Id)
- WHERE
- c.TeamId = :TeamId
- AND cm.UserId = :UserId
- AND c.DeleteAt = 0
- )
- ORDER BY
- c.DisplayName
- LIMIT :Limit
- OFFSET :Offset
- `, map[string]interface{}{
- "TeamId": teamId,
- "UserId": userId,
- "Limit": limit,
- "Offset": offset,
- })
-
- if err != nil {
- result.Err = model.NewAppError("SqlChannelStore.GetMoreChannels", "store.sql_channel.get_more_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
- return
- }
-
- result.Data = data
- })
-}
-
-func (s SqlChannelStoreExperimental) GetPublicChannelsForTeam(teamId string, offset int, limit int) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.GetPublicChannelsForTeam(teamId, offset, limit)
- }
-
- return store.Do(func(result *store.StoreResult) {
- data := &model.ChannelList{}
- _, err := s.GetReplica().Select(data, `
- SELECT
- Channels.*
- FROM
- Channels
- JOIN
- PublicChannels pc ON (pc.Id = Channels.Id)
- WHERE
- pc.TeamId = :TeamId
- AND pc.DeleteAt = 0
- ORDER BY pc.DisplayName
- LIMIT :Limit
- OFFSET :Offset
- `, map[string]interface{}{
- "TeamId": teamId,
- "Limit": limit,
- "Offset": offset,
- })
-
- if err != nil {
- result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsForTeam", "store.sql_channel.get_public_channels.get.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError)
- return
- }
-
- result.Data = data
- })
-}
-
-func (s SqlChannelStoreExperimental) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.GetPublicChannelsByIdsForTeam(teamId, channelIds)
- }
-
- return store.Do(func(result *store.StoreResult) {
- props := make(map[string]interface{})
- props["teamId"] = teamId
-
- idQuery := ""
-
- for index, channelId := range channelIds {
- if len(idQuery) > 0 {
- idQuery += ", "
- }
-
- props["channelId"+strconv.Itoa(index)] = channelId
- idQuery += ":channelId" + strconv.Itoa(index)
- }
-
- data := &model.ChannelList{}
- _, err := s.GetReplica().Select(data, `
- SELECT
- Channels.*
- FROM
- Channels
- JOIN
- PublicChannels pc ON (pc.Id = Channels.Id)
- WHERE
- pc.TeamId = :teamId
- AND pc.DeleteAt = 0
- AND pc.Id IN (`+idQuery+`)
- ORDER BY pc.DisplayName
- `, props)
-
- if err != nil {
- result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.get.app_error", nil, err.Error(), http.StatusInternalServerError)
- }
-
- if len(*data) == 0 {
- result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.not_found.app_error", nil, "", http.StatusNotFound)
- }
-
- result.Data = data
- })
-}
-
-func (s SqlChannelStoreExperimental) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.AutocompleteInTeam(teamId, term, includeDeleted)
- }
-
- return store.Do(func(result *store.StoreResult) {
- deleteFilter := "AND c.DeleteAt = 0"
- if includeDeleted {
- deleteFilter = ""
- }
-
- queryFormat := `
- SELECT
- Channels.*
- FROM
- Channels
- JOIN
- PublicChannels c ON (c.Id = Channels.Id)
- WHERE
- c.TeamId = :TeamId
- ` + deleteFilter + `
- %v
- LIMIT 50
- `
-
- var channels model.ChannelList
-
- if likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose"); likeClause == "" {
- if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil {
- result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
- }
- } else {
- // Using a UNION results in index_merge and fulltext queries and is much faster than the ref
- // query you would get using an OR of the LIKE and full-text clauses.
- fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
- likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
- fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
- query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
-
- if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil {
- result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
- }
- }
-
- sort.Slice(channels, func(a, b int) bool {
- return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName)
- })
- result.Data = &channels
- })
-}
-
-func (s SqlChannelStoreExperimental) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.SearchInTeam(teamId, term, includeDeleted)
- }
-
- return store.Do(func(result *store.StoreResult) {
- deleteFilter := "AND c.DeleteAt = 0"
- if includeDeleted {
- deleteFilter = ""
- }
-
- *result = s.performSearch(`
- SELECT
- Channels.*
- FROM
- Channels
- JOIN
- PublicChannels c ON (c.Id = Channels.Id)
- WHERE
- c.TeamId = :TeamId
- `+deleteFilter+`
- SEARCH_CLAUSE
- ORDER BY c.DisplayName
- LIMIT 100
- `, term, map[string]interface{}{
- "TeamId": teamId,
- })
- })
-}
-
-func (s SqlChannelStoreExperimental) SearchMore(userId string, teamId string, term string) store.StoreChannel {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.SearchMore(userId, teamId, term)
- }
-
- return store.Do(func(result *store.StoreResult) {
- *result = s.performSearch(`
- SELECT
- Channels.*
- FROM
- Channels
- JOIN
- PublicChannels c ON (c.Id = Channels.Id)
- WHERE
- c.TeamId = :TeamId
- AND c.DeleteAt = 0
- AND c.Id NOT IN (
- SELECT
- c.Id
- FROM
- PublicChannels c
- JOIN
- ChannelMembers cm ON (cm.ChannelId = c.Id)
- WHERE
- c.TeamId = :TeamId
- AND cm.UserId = :UserId
- AND c.DeleteAt = 0
- )
- SEARCH_CLAUSE
- ORDER BY c.DisplayName
- LIMIT 100
- `, term, map[string]interface{}{
- "TeamId": teamId,
- "UserId": userId,
- })
- })
-}
-
-func (s SqlChannelStoreExperimental) buildLIKEClause(term string, searchColumns string) (likeClause, likeTerm string) {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.buildLIKEClause(term, searchColumns)
- }
-
- likeTerm = term
-
- // These chars must be removed from the like query.
- for _, c := range ignoreLikeSearchChar {
- likeTerm = strings.Replace(likeTerm, c, "", -1)
- }
-
- // These chars must be escaped in the like query.
- for _, c := range escapeLikeSearchChar {
- likeTerm = strings.Replace(likeTerm, c, "*"+c, -1)
- }
-
- if likeTerm == "" {
- return
- }
-
- // Prepare the LIKE portion of the query.
- var searchFields []string
- for _, field := range strings.Split(searchColumns, ", ") {
- if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
- searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*'", field, ":LikeTerm"))
- } else {
- searchFields = append(searchFields, fmt.Sprintf("%s LIKE %s escape '*'", field, ":LikeTerm"))
- }
- }
-
- likeClause = fmt.Sprintf("(%s)", strings.Join(searchFields, " OR "))
- likeTerm += "%"
- return
-}
-
-func (s SqlChannelStoreExperimental) buildFulltextClause(term string, searchColumns string) (fulltextClause, fulltextTerm string) {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.buildFulltextClause(term, searchColumns)
- }
-
- // Copy the terms as we will need to prepare them differently for each search type.
- fulltextTerm = term
-
- // These chars must be treated as spaces in the fulltext query.
- for _, c := range spaceFulltextSearchChar {
- fulltextTerm = strings.Replace(fulltextTerm, c, " ", -1)
- }
-
- // Prepare the FULLTEXT portion of the query.
- if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
- fulltextTerm = strings.Replace(fulltextTerm, "|", "", -1)
-
- splitTerm := strings.Fields(fulltextTerm)
- for i, t := range strings.Fields(fulltextTerm) {
- if i == len(splitTerm)-1 {
- splitTerm[i] = t + ":*"
- } else {
- splitTerm[i] = t + ":* &"
- }
- }
-
- fulltextTerm = strings.Join(splitTerm, " ")
-
- fulltextClause = fmt.Sprintf("((%s) @@ to_tsquery(:FulltextTerm))", convertMySQLFullTextColumnsToPostgres(searchColumns))
- } else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
- splitTerm := strings.Fields(fulltextTerm)
- for i, t := range strings.Fields(fulltextTerm) {
- splitTerm[i] = "+" + t + "*"
- }
-
- fulltextTerm = strings.Join(splitTerm, " ")
-
- fulltextClause = fmt.Sprintf("MATCH(%s) AGAINST (:FulltextTerm IN BOOLEAN MODE)", searchColumns)
- }
-
- return
-}
-
-func (s SqlChannelStoreExperimental) performSearch(searchQuery string, term string, parameters map[string]interface{}) store.StoreResult {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- return s.SqlChannelStore.performSearch(searchQuery, term, parameters)
- }
-
- result := store.StoreResult{}
-
- likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
- if likeTerm == "" {
- // If the likeTerm is empty after preparing, then don't bother searching.
- searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1)
- } else {
- parameters["LikeTerm"] = likeTerm
- fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
- parameters["FulltextTerm"] = fulltextTerm
- searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1)
- }
-
- var channels model.ChannelList
-
- if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil {
- result.Err = model.NewAppError("SqlChannelStore.Search", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
- return result
- }
-
- result.Data = &channels
- return result
-}
-
-func (s SqlChannelStoreExperimental) EnableExperimentalPublicChannelsMaterialization() {
- if !s.IsExperimentalPublicChannelsMaterializationEnabled() {
- mlog.Info("Enabling experimental public channels materialization")
- }
-
- atomic.StoreUint32(s.experimentalPublicChannelsMaterializationDisabled, 0)
-}
-
-func (s SqlChannelStoreExperimental) DisableExperimentalPublicChannelsMaterialization() {
- if s.IsExperimentalPublicChannelsMaterializationEnabled() {
- mlog.Info("Disabling experimental public channels materialization")
- }
-
- atomic.StoreUint32(s.experimentalPublicChannelsMaterializationDisabled, 1)
-}
-
-func (s SqlChannelStoreExperimental) IsExperimentalPublicChannelsMaterializationEnabled() bool {
- return atomic.LoadUint32(s.experimentalPublicChannelsMaterializationDisabled) == 0
-}
diff --git a/store/sqlstore/supplier.go b/store/sqlstore/supplier.go
index 2fc299d..c0c92aa 100644
--- a/store/sqlstore/supplier.go
+++ b/store/sqlstore/supplier.go
@@ -118,13 +118,8 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
supplier.initConnection()
- enableExperimentalPublicChannelsMaterialization := true
- if settings.EnablePublicChannelsMaterialization != nil && !*settings.EnablePublicChannelsMaterialization {
- enableExperimentalPublicChannelsMaterialization = false
- }
-
supplier.oldStores.team = NewSqlTeamStore(supplier)
- supplier.oldStores.channel = NewSqlChannelStoreExperimental(supplier, metrics, enableExperimentalPublicChannelsMaterialization)
+ supplier.oldStores.channel = NewSqlChannelStore(supplier, metrics)
supplier.oldStores.post = NewSqlPostStore(supplier, metrics)
supplier.oldStores.user = NewSqlUserStore(supplier, metrics)
supplier.oldStores.audit = NewSqlAuditStore(supplier)
@@ -162,7 +157,7 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
UpgradeDatabase(supplier)
supplier.oldStores.team.(*SqlTeamStore).CreateIndexesIfNotExists()
- supplier.oldStores.channel.(*SqlChannelStoreExperimental).CreateIndexesIfNotExists()
+ supplier.oldStores.channel.(*SqlChannelStore).CreateIndexesIfNotExists()
supplier.oldStores.post.(*SqlPostStore).CreateIndexesIfNotExists()
supplier.oldStores.user.(*SqlUserStore).CreateIndexesIfNotExists()
supplier.oldStores.audit.(*SqlAuditStore).CreateIndexesIfNotExists()
diff --git a/store/store.go b/store/store.go
index e554f14..eefaa46 100644
--- a/store/store.go
+++ b/store/store.go
@@ -179,10 +179,6 @@ type ChannelStore interface {
ClearAllCustomRoleAssignments() StoreChannel
ResetLastPostAt() StoreChannel
MigratePublicChannels() error
- DropPublicChannels() error
- EnableExperimentalPublicChannelsMaterialization()
- DisableExperimentalPublicChannelsMaterialization()
- IsExperimentalPublicChannelsMaterializationEnabled() bool
GetAllChannelsForExportAfter(limit int, afterId string) StoreChannel
GetChannelMembersForExport(userId string, teamId string) StoreChannel
RemoveAllDeactivatedMembers(channelId string) StoreChannel
diff --git a/store/storetest/channel_store.go b/store/storetest/channel_store.go
index 34efd81..7fc4190 100644
--- a/store/storetest/channel_store.go
+++ b/store/storetest/channel_store.go
@@ -24,65 +24,48 @@ type SqlSupplier interface {
func TestChannelStore(t *testing.T, ss store.Store, s SqlSupplier) {
createDefaultRoles(t, ss)
- for _, enabled := range []bool{true, false} {
- description := "experimental materialization"
- if enabled {
- description += " enabled"
- ss.Channel().EnableExperimentalPublicChannelsMaterialization()
- } else {
- description += " disabled"
- ss.Channel().DisableExperimentalPublicChannelsMaterialization()
-
- // Additionally drop the public channels table and all associated triggers
- // to prove that the experimental store is fully disabled.
- ss.Channel().DropPublicChannels()
- }
-
- t.Run(description, func(t *testing.T) {
- t.Run("Save", func(t *testing.T) { testChannelStoreSave(t, ss) })
- t.Run("SaveDirectChannel", func(t *testing.T) { testChannelStoreSaveDirectChannel(t, ss) })
- t.Run("CreateDirectChannel", func(t *testing.T) { testChannelStoreCreateDirectChannel(t, ss) })
- t.Run("Update", func(t *testing.T) { testChannelStoreUpdate(t, ss) })
- t.Run("GetChannelUnread", func(t *testing.T) { testGetChannelUnread(t, ss) })
- t.Run("Get", func(t *testing.T) { testChannelStoreGet(t, ss) })
- t.Run("GetForPost", func(t *testing.T) { testChannelStoreGetForPost(t, ss) })
- t.Run("Restore", func(t *testing.T) { testChannelStoreRestore(t, ss) })
- t.Run("Delete", func(t *testing.T) { testChannelStoreDelete(t, ss) })
- t.Run("GetByName", func(t *testing.T) { testChannelStoreGetByName(t, ss) })
- t.Run("GetByNames", func(t *testing.T) { testChannelStoreGetByNames(t, ss) })
- t.Run("GetDeletedByName", func(t *testing.T) { testChannelStoreGetDeletedByName(t, ss) })
- t.Run("GetDeleted", func(t *testing.T) { testChannelStoreGetDeleted(t, ss) })
- t.Run("ChannelMemberStore", func(t *testing.T) { testChannelMemberStore(t, ss) })
- t.Run("ChannelDeleteMemberStore", func(t *testing.T) { testChannelDeleteMemberStore(t, ss) })
- t.Run("GetChannels", func(t *testing.T) { testChannelStoreGetChannels(t, ss) })
- t.Run("GetMoreChannels", func(t *testing.T) { testChannelStoreGetMoreChannels(t, ss) })
- t.Run("GetPublicChannelsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsForTeam(t, ss) })
- t.Run("GetPublicChannelsByIdsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsByIdsForTeam(t, ss) })
- t.Run("GetChannelCounts", func(t *testing.T) { testChannelStoreGetChannelCounts(t, ss) })
- t.Run("GetMembersForUser", func(t *testing.T) { testChannelStoreGetMembersForUser(t, ss) })
- t.Run("UpdateLastViewedAt", func(t *testing.T) { testChannelStoreUpdateLastViewedAt(t, ss) })
- t.Run("IncrementMentionCount", func(t *testing.T) { testChannelStoreIncrementMentionCount(t, ss) })
- t.Run("UpdateChannelMember", func(t *testing.T) { testUpdateChannelMember(t, ss) })
- t.Run("GetMember", func(t *testing.T) { testGetMember(t, ss) })
- t.Run("GetMemberForPost", func(t *testing.T) { testChannelStoreGetMemberForPost(t, ss) })
- t.Run("GetMemberCount", func(t *testing.T) { testGetMemberCount(t, ss) })
- t.Run("SearchMore", func(t *testing.T) { testChannelStoreSearchMore(t, ss) })
- t.Run("SearchInTeam", func(t *testing.T) { testChannelStoreSearchInTeam(t, ss) })
- t.Run("AutocompleteInTeamForSearch", func(t *testing.T) { testChannelStoreAutocompleteInTeamForSearch(t, ss) })
- t.Run("GetMembersByIds", func(t *testing.T) { testChannelStoreGetMembersByIds(t, ss) })
- t.Run("AnalyticsDeletedTypeCount", func(t *testing.T) { testChannelStoreAnalyticsDeletedTypeCount(t, ss) })
- t.Run("GetPinnedPosts", func(t *testing.T) { testChannelStoreGetPinnedPosts(t, ss) })
- t.Run("MaxChannelsPerTeam", func(t *testing.T) { testChannelStoreMaxChannelsPerTeam(t, ss) })
- t.Run("GetChannelsByScheme", func(t *testing.T) { testChannelStoreGetChannelsByScheme(t, ss) })
- t.Run("MigrateChannelMembers", func(t *testing.T) { testChannelStoreMigrateChannelMembers(t, ss) })
- t.Run("ResetAllChannelSchemes", func(t *testing.T) { testResetAllChannelSchemes(t, ss) })
- t.Run("ClearAllCustomRoleAssignments", func(t *testing.T) { testChannelStoreClearAllCustomRoleAssignments(t, ss) })
- t.Run("MaterializedPublicChannels", func(t *testing.T) { testMaterializedPublicChannels(t, ss, s) })
- t.Run("GetAllChannelsForExportAfter", func(t *testing.T) { testChannelStoreGetAllChannelsForExportAfter(t, ss) })
- t.Run("GetChannelMembersForExport", func(t *testing.T) { testChannelStoreGetChannelMembersForExport(t, ss) })
- t.Run("RemoveAllDeactivatedMembers", func(t *testing.T) { testChannelStoreRemoveAllDeactivatedMembers(t, ss) })
- })
- }
+ t.Run("Save", func(t *testing.T) { testChannelStoreSave(t, ss) })
+ t.Run("SaveDirectChannel", func(t *testing.T) { testChannelStoreSaveDirectChannel(t, ss) })
+ t.Run("CreateDirectChannel", func(t *testing.T) { testChannelStoreCreateDirectChannel(t, ss) })
+ t.Run("Update", func(t *testing.T) { testChannelStoreUpdate(t, ss) })
+ t.Run("GetChannelUnread", func(t *testing.T) { testGetChannelUnread(t, ss) })
+ t.Run("Get", func(t *testing.T) { testChannelStoreGet(t, ss) })
+ t.Run("GetForPost", func(t *testing.T) { testChannelStoreGetForPost(t, ss) })
+ t.Run("Restore", func(t *testing.T) { testChannelStoreRestore(t, ss) })
+ t.Run("Delete", func(t *testing.T) { testChannelStoreDelete(t, ss) })
+ t.Run("GetByName", func(t *testing.T) { testChannelStoreGetByName(t, ss) })
+ t.Run("GetByNames", func(t *testing.T) { testChannelStoreGetByNames(t, ss) })
+ t.Run("GetDeletedByName", func(t *testing.T) { testChannelStoreGetDeletedByName(t, ss) })
+ t.Run("GetDeleted", func(t *testing.T) { testChannelStoreGetDeleted(t, ss) })
+ t.Run("ChannelMemberStore", func(t *testing.T) { testChannelMemberStore(t, ss) })
+ t.Run("ChannelDeleteMemberStore", func(t *testing.T) { testChannelDeleteMemberStore(t, ss) })
+ t.Run("GetChannels", func(t *testing.T) { testChannelStoreGetChannels(t, ss) })
+ t.Run("GetMoreChannels", func(t *testing.T) { testChannelStoreGetMoreChannels(t, ss) })
+ t.Run("GetPublicChannelsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsForTeam(t, ss) })
+ t.Run("GetPublicChannelsByIdsForTeam", func(t *testing.T) { testChannelStoreGetPublicChannelsByIdsForTeam(t, ss) })
+ t.Run("GetChannelCounts", func(t *testing.T) { testChannelStoreGetChannelCounts(t, ss) })
+ t.Run("GetMembersForUser", func(t *testing.T) { testChannelStoreGetMembersForUser(t, ss) })
+ t.Run("UpdateLastViewedAt", func(t *testing.T) { testChannelStoreUpdateLastViewedAt(t, ss) })
+ t.Run("IncrementMentionCount", func(t *testing.T) { testChannelStoreIncrementMentionCount(t, ss) })
+ t.Run("UpdateChannelMember", func(t *testing.T) { testUpdateChannelMember(t, ss) })
+ t.Run("GetMember", func(t *testing.T) { testGetMember(t, ss) })
+ t.Run("GetMemberForPost", func(t *testing.T) { testChannelStoreGetMemberForPost(t, ss) })
+ t.Run("GetMemberCount", func(t *testing.T) { testGetMemberCount(t, ss) })
+ t.Run("SearchMore", func(t *testing.T) { testChannelStoreSearchMore(t, ss) })
+ t.Run("SearchInTeam", func(t *testing.T) { testChannelStoreSearchInTeam(t, ss) })
+ t.Run("AutocompleteInTeamForSearch", func(t *testing.T) { testChannelStoreAutocompleteInTeamForSearch(t, ss) })
+ t.Run("GetMembersByIds", func(t *testing.T) { testChannelStoreGetMembersByIds(t, ss) })
+ t.Run("AnalyticsDeletedTypeCount", func(t *testing.T) { testChannelStoreAnalyticsDeletedTypeCount(t, ss) })
+ t.Run("GetPinnedPosts", func(t *testing.T) { testChannelStoreGetPinnedPosts(t, ss) })
+ t.Run("MaxChannelsPerTeam", func(t *testing.T) { testChannelStoreMaxChannelsPerTeam(t, ss) })
+ t.Run("GetChannelsByScheme", func(t *testing.T) { testChannelStoreGetChannelsByScheme(t, ss) })
+ t.Run("MigrateChannelMembers", func(t *testing.T) { testChannelStoreMigrateChannelMembers(t, ss) })
+ t.Run("ResetAllChannelSchemes", func(t *testing.T) { testResetAllChannelSchemes(t, ss) })
+ t.Run("ClearAllCustomRoleAssignments", func(t *testing.T) { testChannelStoreClearAllCustomRoleAssignments(t, ss) })
+ t.Run("MaterializedPublicChannels", func(t *testing.T) { testMaterializedPublicChannels(t, ss, s) })
+ t.Run("GetAllChannelsForExportAfter", func(t *testing.T) { testChannelStoreGetAllChannelsForExportAfter(t, ss) })
+ t.Run("GetChannelMembersForExport", func(t *testing.T) { testChannelStoreGetChannelMembersForExport(t, ss) })
+ t.Run("RemoveAllDeactivatedMembers", func(t *testing.T) { testChannelStoreRemoveAllDeactivatedMembers(t, ss) })
}
func testChannelStoreSave(t *testing.T, ss store.Store) {
@@ -2574,10 +2557,6 @@ func testChannelStoreClearAllCustomRoleAssignments(t *testing.T, ss store.Store)
// testMaterializedPublicChannels tests edge cases involving the triggers and stored procedures
// that materialize the PublicChannels table.
func testMaterializedPublicChannels(t *testing.T, ss store.Store, s SqlSupplier) {
- if !ss.Channel().IsExperimentalPublicChannelsMaterializationEnabled() {
- return
- }
-
teamId := model.NewId()
// o1 is a public channel on the team
diff --git a/store/storetest/mocks/ChannelStore.go b/store/storetest/mocks/ChannelStore.go
index 7ad8f10..b12d2a0 100644
--- a/store/storetest/mocks/ChannelStore.go
+++ b/store/storetest/mocks/ChannelStore.go
@@ -130,30 +130,6 @@ func (_m *ChannelStore) Delete(channelId string, time int64) store.StoreChannel
return r0
}
-// DisableExperimentalPublicChannelsMaterialization provides a mock function with given fields:
-func (_m *ChannelStore) DisableExperimentalPublicChannelsMaterialization() {
- _m.Called()
-}
-
-// DropPublicChannels provides a mock function with given fields:
-func (_m *ChannelStore) DropPublicChannels() error {
- ret := _m.Called()
-
- var r0 error
- if rf, ok := ret.Get(0).(func() error); ok {
- r0 = rf()
- } else {
- r0 = ret.Error(0)
- }
-
- return r0
-}
-
-// EnableExperimentalPublicChannelsMaterialization provides a mock function with given fields:
-func (_m *ChannelStore) EnableExperimentalPublicChannelsMaterialization() {
- _m.Called()
-}
-
// Get provides a mock function with given fields: id, allowFromCache
func (_m *ChannelStore) Get(id string, allowFromCache bool) store.StoreChannel {
ret := _m.Called(id, allowFromCache)
@@ -673,20 +649,6 @@ func (_m *ChannelStore) InvalidateMemberCount(channelId string) {
_m.Called(channelId)
}
-// IsExperimentalPublicChannelsMaterializationEnabled provides a mock function with given fields:
-func (_m *ChannelStore) IsExperimentalPublicChannelsMaterializationEnabled() bool {
- ret := _m.Called()
-
- var r0 bool
- if rf, ok := ret.Get(0).(func() bool); ok {
- r0 = rf()
- } else {
- r0 = ret.Get(0).(bool)
- }
-
- return r0
-}
-
// IsUserInChannelUseCache provides a mock function with given fields: userId, channelId
func (_m *ChannelStore) IsUserInChannelUseCache(userId string, channelId string) bool {
ret := _m.Called(userId, channelId)