github.com/RajatVaryani/mattermost-server@v5.11.1+incompatible/store/sqlstore/channel_store.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package sqlstore
     5  
     6  import (
     7  	"database/sql"
     8  	"fmt"
     9  	"net/http"
    10  	"sort"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"github.com/mattermost/gorp"
    15  	"github.com/pkg/errors"
    16  
    17  	sq "github.com/Masterminds/squirrel"
    18  	"github.com/mattermost/mattermost-server/einterfaces"
    19  	"github.com/mattermost/mattermost-server/mlog"
    20  	"github.com/mattermost/mattermost-server/model"
    21  	"github.com/mattermost/mattermost-server/store"
    22  	"github.com/mattermost/mattermost-server/utils"
    23  )
    24  
    25  const (
    26  	ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE = model.SESSION_CACHE_SIZE
    27  	ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SEC  = 900 // 15 mins
    28  
    29  	ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE = model.SESSION_CACHE_SIZE
    30  	ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SEC  = 1800 // 30 mins
    31  
    32  	CHANNEL_MEMBERS_COUNTS_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
    33  	CHANNEL_MEMBERS_COUNTS_CACHE_SEC  = 1800 // 30 mins
    34  
    35  	CHANNEL_CACHE_SEC = 900 // 15 mins
    36  )
    37  
    38  type SqlChannelStore struct {
    39  	SqlStore
    40  	metrics einterfaces.MetricsInterface
    41  }
    42  
    43  type channelMember struct {
    44  	ChannelId    string
    45  	UserId       string
    46  	Roles        string
    47  	LastViewedAt int64
    48  	MsgCount     int64
    49  	MentionCount int64
    50  	NotifyProps  model.StringMap
    51  	LastUpdateAt int64
    52  	SchemeUser   sql.NullBool
    53  	SchemeAdmin  sql.NullBool
    54  }
    55  
    56  func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
    57  	return &channelMember{
    58  		ChannelId:    cm.ChannelId,
    59  		UserId:       cm.UserId,
    60  		Roles:        cm.ExplicitRoles,
    61  		LastViewedAt: cm.LastViewedAt,
    62  		MsgCount:     cm.MsgCount,
    63  		MentionCount: cm.MentionCount,
    64  		NotifyProps:  cm.NotifyProps,
    65  		LastUpdateAt: cm.LastUpdateAt,
    66  		SchemeUser:   sql.NullBool{Valid: true, Bool: cm.SchemeUser},
    67  		SchemeAdmin:  sql.NullBool{Valid: true, Bool: cm.SchemeAdmin},
    68  	}
    69  }
    70  
    71  type channelMemberWithSchemeRoles struct {
    72  	ChannelId                     string
    73  	UserId                        string
    74  	Roles                         string
    75  	LastViewedAt                  int64
    76  	MsgCount                      int64
    77  	MentionCount                  int64
    78  	NotifyProps                   model.StringMap
    79  	LastUpdateAt                  int64
    80  	SchemeUser                    sql.NullBool
    81  	SchemeAdmin                   sql.NullBool
    82  	TeamSchemeDefaultUserRole     sql.NullString
    83  	TeamSchemeDefaultAdminRole    sql.NullString
    84  	ChannelSchemeDefaultUserRole  sql.NullString
    85  	ChannelSchemeDefaultAdminRole sql.NullString
    86  }
    87  
    88  type channelMemberWithSchemeRolesList []channelMemberWithSchemeRoles
    89  
    90  func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
    91  	var roles []string
    92  	var explicitRoles []string
    93  
    94  	// Identify any system-wide scheme derived roles that are in "Roles" field due to not yet being migrated,
    95  	// and exclude them from ExplicitRoles field.
    96  	schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
    97  	schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
    98  	for _, role := range strings.Fields(db.Roles) {
    99  		isImplicit := false
   100  		if role == model.CHANNEL_USER_ROLE_ID {
   101  			// We have an implicit role via the system scheme. Override the "schemeUser" field to true.
   102  			schemeUser = true
   103  			isImplicit = true
   104  		} else if role == model.CHANNEL_ADMIN_ROLE_ID {
   105  			// We have an implicit role via the system scheme.
   106  			schemeAdmin = true
   107  			isImplicit = true
   108  		}
   109  
   110  		if !isImplicit {
   111  			explicitRoles = append(explicitRoles, role)
   112  		}
   113  		roles = append(roles, role)
   114  	}
   115  
   116  	// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
   117  	// them to the Roles field for backwards compatibility reasons.
   118  	var schemeImpliedRoles []string
   119  	if db.SchemeUser.Valid && db.SchemeUser.Bool {
   120  		if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" {
   121  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String)
   122  		} else if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" {
   123  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String)
   124  		} else {
   125  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID)
   126  		}
   127  	}
   128  	if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool {
   129  		if db.ChannelSchemeDefaultAdminRole.Valid && db.ChannelSchemeDefaultAdminRole.String != "" {
   130  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultAdminRole.String)
   131  		} else if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" {
   132  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String)
   133  		} else {
   134  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID)
   135  		}
   136  	}
   137  	for _, impliedRole := range schemeImpliedRoles {
   138  		alreadyThere := false
   139  		for _, role := range roles {
   140  			if role == impliedRole {
   141  				alreadyThere = true
   142  			}
   143  		}
   144  		if !alreadyThere {
   145  			roles = append(roles, impliedRole)
   146  		}
   147  	}
   148  
   149  	return &model.ChannelMember{
   150  		ChannelId:     db.ChannelId,
   151  		UserId:        db.UserId,
   152  		Roles:         strings.Join(roles, " "),
   153  		LastViewedAt:  db.LastViewedAt,
   154  		MsgCount:      db.MsgCount,
   155  		MentionCount:  db.MentionCount,
   156  		NotifyProps:   db.NotifyProps,
   157  		LastUpdateAt:  db.LastUpdateAt,
   158  		SchemeAdmin:   schemeAdmin,
   159  		SchemeUser:    schemeUser,
   160  		ExplicitRoles: strings.Join(explicitRoles, " "),
   161  	}
   162  }
   163  
   164  func (db channelMemberWithSchemeRolesList) ToModel() *model.ChannelMembers {
   165  	cms := model.ChannelMembers{}
   166  
   167  	for _, cm := range db {
   168  		cms = append(cms, *cm.ToModel())
   169  	}
   170  
   171  	return &cms
   172  }
   173  
   174  type allChannelMember struct {
   175  	ChannelId                     string
   176  	Roles                         string
   177  	SchemeUser                    sql.NullBool
   178  	SchemeAdmin                   sql.NullBool
   179  	TeamSchemeDefaultUserRole     sql.NullString
   180  	TeamSchemeDefaultAdminRole    sql.NullString
   181  	ChannelSchemeDefaultUserRole  sql.NullString
   182  	ChannelSchemeDefaultAdminRole sql.NullString
   183  }
   184  
   185  type allChannelMembers []allChannelMember
   186  
   187  func (db allChannelMember) Process() (string, string) {
   188  	roles := strings.Fields(db.Roles)
   189  
   190  	// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
   191  	// them to the Roles field for backwards compatibility reasons.
   192  	var schemeImpliedRoles []string
   193  	if db.SchemeUser.Valid && db.SchemeUser.Bool {
   194  		if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" {
   195  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String)
   196  		} else if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" {
   197  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String)
   198  		} else {
   199  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID)
   200  		}
   201  	}
   202  	if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool {
   203  		if db.ChannelSchemeDefaultAdminRole.Valid && db.ChannelSchemeDefaultAdminRole.String != "" {
   204  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultAdminRole.String)
   205  		} else if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" {
   206  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String)
   207  		} else {
   208  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID)
   209  		}
   210  	}
   211  	for _, impliedRole := range schemeImpliedRoles {
   212  		alreadyThere := false
   213  		for _, role := range roles {
   214  			if role == impliedRole {
   215  				alreadyThere = true
   216  			}
   217  		}
   218  		if !alreadyThere {
   219  			roles = append(roles, impliedRole)
   220  		}
   221  	}
   222  
   223  	return db.ChannelId, strings.Join(roles, " ")
   224  }
   225  
   226  func (db allChannelMembers) ToMapStringString() map[string]string {
   227  	result := make(map[string]string)
   228  
   229  	for _, item := range db {
   230  		key, value := item.Process()
   231  		result[key] = value
   232  	}
   233  
   234  	return result
   235  }
   236  
   237  // publicChannel is a subset of the metadata corresponding to public channels only.
   238  type publicChannel struct {
   239  	Id          string `json:"id"`
   240  	DeleteAt    int64  `json:"delete_at"`
   241  	TeamId      string `json:"team_id"`
   242  	DisplayName string `json:"display_name"`
   243  	Name        string `json:"name"`
   244  	Header      string `json:"header"`
   245  	Purpose     string `json:"purpose"`
   246  }
   247  
   248  var channelMemberCountsCache = utils.NewLru(CHANNEL_MEMBERS_COUNTS_CACHE_SIZE)
   249  var allChannelMembersForUserCache = utils.NewLru(ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE)
   250  var allChannelMembersNotifyPropsForChannelCache = utils.NewLru(ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE)
   251  var channelCache = utils.NewLru(model.CHANNEL_CACHE_SIZE)
   252  var channelByNameCache = utils.NewLru(model.CHANNEL_CACHE_SIZE)
   253  
   254  func (s SqlChannelStore) ClearCaches() {
   255  	channelMemberCountsCache.Purge()
   256  	allChannelMembersForUserCache.Purge()
   257  	allChannelMembersNotifyPropsForChannelCache.Purge()
   258  	channelCache.Purge()
   259  	channelByNameCache.Purge()
   260  
   261  	if s.metrics != nil {
   262  		s.metrics.IncrementMemCacheInvalidationCounter("Channel Member Counts - Purge")
   263  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Purge")
   264  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Purge")
   265  		s.metrics.IncrementMemCacheInvalidationCounter("Channel - Purge")
   266  		s.metrics.IncrementMemCacheInvalidationCounter("Channel By Name - Purge")
   267  	}
   268  }
   269  
   270  func NewSqlChannelStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.ChannelStore {
   271  	s := &SqlChannelStore{
   272  		SqlStore: sqlStore,
   273  		metrics:  metrics,
   274  	}
   275  
   276  	for _, db := range sqlStore.GetAllConns() {
   277  		table := db.AddTableWithName(model.Channel{}, "Channels").SetKeys(false, "Id")
   278  		table.ColMap("Id").SetMaxSize(26)
   279  		table.ColMap("TeamId").SetMaxSize(26)
   280  		table.ColMap("Type").SetMaxSize(1)
   281  		table.ColMap("DisplayName").SetMaxSize(64)
   282  		table.ColMap("Name").SetMaxSize(64)
   283  		table.SetUniqueTogether("Name", "TeamId")
   284  		table.ColMap("Header").SetMaxSize(1024)
   285  		table.ColMap("Purpose").SetMaxSize(250)
   286  		table.ColMap("CreatorId").SetMaxSize(26)
   287  		table.ColMap("SchemeId").SetMaxSize(26)
   288  
   289  		tablem := db.AddTableWithName(channelMember{}, "ChannelMembers").SetKeys(false, "ChannelId", "UserId")
   290  		tablem.ColMap("ChannelId").SetMaxSize(26)
   291  		tablem.ColMap("UserId").SetMaxSize(26)
   292  		tablem.ColMap("Roles").SetMaxSize(64)
   293  		tablem.ColMap("NotifyProps").SetMaxSize(2000)
   294  
   295  		tablePublicChannels := db.AddTableWithName(publicChannel{}, "PublicChannels").SetKeys(false, "Id")
   296  		tablePublicChannels.ColMap("Id").SetMaxSize(26)
   297  		tablePublicChannels.ColMap("TeamId").SetMaxSize(26)
   298  		tablePublicChannels.ColMap("DisplayName").SetMaxSize(64)
   299  		tablePublicChannels.ColMap("Name").SetMaxSize(64)
   300  		tablePublicChannels.SetUniqueTogether("Name", "TeamId")
   301  		tablePublicChannels.ColMap("Header").SetMaxSize(1024)
   302  		tablePublicChannels.ColMap("Purpose").SetMaxSize(250)
   303  	}
   304  
   305  	return s
   306  }
   307  
   308  func (s SqlChannelStore) CreateIndexesIfNotExists() {
   309  	s.CreateIndexIfNotExists("idx_channels_team_id", "Channels", "TeamId")
   310  	s.CreateIndexIfNotExists("idx_channels_name", "Channels", "Name")
   311  	s.CreateIndexIfNotExists("idx_channels_update_at", "Channels", "UpdateAt")
   312  	s.CreateIndexIfNotExists("idx_channels_create_at", "Channels", "CreateAt")
   313  	s.CreateIndexIfNotExists("idx_channels_delete_at", "Channels", "DeleteAt")
   314  
   315  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   316  		s.CreateIndexIfNotExists("idx_channels_name_lower", "Channels", "lower(Name)")
   317  		s.CreateIndexIfNotExists("idx_channels_displayname_lower", "Channels", "lower(DisplayName)")
   318  	}
   319  
   320  	s.CreateIndexIfNotExists("idx_channelmembers_channel_id", "ChannelMembers", "ChannelId")
   321  	s.CreateIndexIfNotExists("idx_channelmembers_user_id", "ChannelMembers", "UserId")
   322  
   323  	s.CreateFullTextIndexIfNotExists("idx_channel_search_txt", "Channels", "Name, DisplayName, Purpose")
   324  
   325  	s.CreateIndexIfNotExists("idx_publicchannels_team_id", "PublicChannels", "TeamId")
   326  	s.CreateIndexIfNotExists("idx_publicchannels_name", "PublicChannels", "Name")
   327  	s.CreateIndexIfNotExists("idx_publicchannels_delete_at", "PublicChannels", "DeleteAt")
   328  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   329  		s.CreateIndexIfNotExists("idx_publicchannels_name_lower", "PublicChannels", "lower(Name)")
   330  		s.CreateIndexIfNotExists("idx_publicchannels_displayname_lower", "PublicChannels", "lower(DisplayName)")
   331  	}
   332  	s.CreateFullTextIndexIfNotExists("idx_publicchannels_search_txt", "PublicChannels", "Name, DisplayName, Purpose")
   333  }
   334  
   335  // MigratePublicChannels initializes the PublicChannels table with data created before this version
   336  // of the Mattermost server kept it up-to-date.
   337  func (s SqlChannelStore) MigratePublicChannels() error {
   338  	if _, err := s.GetMaster().Exec(`
   339  		INSERT INTO PublicChannels
   340  		    (Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
   341  		SELECT
   342  		    c.Id, c.DeleteAt, c.TeamId, c.DisplayName, c.Name, c.Header, c.Purpose
   343  		FROM
   344  		    Channels c
   345  		LEFT JOIN
   346  		    PublicChannels pc ON (pc.Id = c.Id)
   347  		WHERE
   348  		    c.Type = 'O'
   349  		AND pc.Id IS NULL
   350  	`); err != nil {
   351  		return err
   352  	}
   353  
   354  	return nil
   355  }
   356  
   357  func (s SqlChannelStore) upsertPublicChannelT(transaction *gorp.Transaction, channel *model.Channel) error {
   358  	publicChannel := &publicChannel{
   359  		Id:          channel.Id,
   360  		DeleteAt:    channel.DeleteAt,
   361  		TeamId:      channel.TeamId,
   362  		DisplayName: channel.DisplayName,
   363  		Name:        channel.Name,
   364  		Header:      channel.Header,
   365  		Purpose:     channel.Purpose,
   366  	}
   367  
   368  	if channel.Type != model.CHANNEL_OPEN {
   369  		if _, err := transaction.Delete(publicChannel); err != nil {
   370  			return errors.Wrap(err, "failed to delete public channel")
   371  		}
   372  
   373  		return nil
   374  	}
   375  
   376  	if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
   377  		// Leverage native upsert for MySQL, since RowsAffected returns 0 if the row exists
   378  		// but no changes were made, breaking the update-then-insert paradigm below when
   379  		// the row already exists. (Postgres 9.4 doesn't support native upsert.)
   380  		if _, err := transaction.Exec(`
   381  			INSERT INTO
   382  			    PublicChannels(Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
   383  			VALUES
   384  			    (:Id, :DeleteAt, :TeamId, :DisplayName, :Name, :Header, :Purpose)
   385  			ON DUPLICATE KEY UPDATE
   386  			    DeleteAt = :DeleteAt,
   387  			    TeamId = :TeamId,
   388  			    DisplayName = :DisplayName,
   389  			    Name = :Name,
   390  			    Header = :Header,
   391  			    Purpose = :Purpose;
   392  		`, map[string]interface{}{
   393  			"Id":          publicChannel.Id,
   394  			"DeleteAt":    publicChannel.DeleteAt,
   395  			"TeamId":      publicChannel.TeamId,
   396  			"DisplayName": publicChannel.DisplayName,
   397  			"Name":        publicChannel.Name,
   398  			"Header":      publicChannel.Header,
   399  			"Purpose":     publicChannel.Purpose,
   400  		}); err != nil {
   401  			return errors.Wrap(err, "failed to insert public channel")
   402  		}
   403  	} else {
   404  		count, err := transaction.Update(publicChannel)
   405  		if err != nil {
   406  			return errors.Wrap(err, "failed to update public channel")
   407  		}
   408  		if count > 0 {
   409  			return nil
   410  		}
   411  
   412  		if err := transaction.Insert(publicChannel); err != nil {
   413  			return errors.Wrap(err, "failed to insert public channel")
   414  		}
   415  	}
   416  
   417  	return nil
   418  }
   419  
   420  // Save writes the (non-direct) channel channel to the database.
   421  func (s SqlChannelStore) Save(channel *model.Channel, maxChannelsPerTeam int64) store.StoreChannel {
   422  	return store.Do(func(result *store.StoreResult) {
   423  		if channel.DeleteAt != 0 {
   424  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest)
   425  			return
   426  		}
   427  
   428  		if channel.Type == model.CHANNEL_DIRECT {
   429  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest)
   430  			return
   431  		}
   432  
   433  		transaction, err := s.GetMaster().Begin()
   434  		if err != nil {
   435  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   436  			return
   437  		}
   438  		defer finalizeTransaction(transaction)
   439  
   440  		*result = s.saveChannelT(transaction, channel, maxChannelsPerTeam)
   441  		if result.Err != nil {
   442  			return
   443  		}
   444  
   445  		// Additionally propagate the write to the PublicChannels table.
   446  		if err := s.upsertPublicChannelT(transaction, result.Data.(*model.Channel)); err != nil {
   447  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.upsert_public_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
   448  			return
   449  		}
   450  
   451  		if err := transaction.Commit(); err != nil {
   452  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   453  			return
   454  		}
   455  	})
   456  }
   457  
   458  func (s SqlChannelStore) CreateDirectChannel(userId string, otherUserId string) store.StoreChannel {
   459  	channel := new(model.Channel)
   460  
   461  	channel.DisplayName = ""
   462  	channel.Name = model.GetDMNameFromIds(otherUserId, userId)
   463  
   464  	channel.Header = ""
   465  	channel.Type = model.CHANNEL_DIRECT
   466  
   467  	cm1 := &model.ChannelMember{
   468  		UserId:      userId,
   469  		NotifyProps: model.GetDefaultChannelNotifyProps(),
   470  		SchemeUser:  true,
   471  	}
   472  	cm2 := &model.ChannelMember{
   473  		UserId:      otherUserId,
   474  		NotifyProps: model.GetDefaultChannelNotifyProps(),
   475  		SchemeUser:  true,
   476  	}
   477  
   478  	return s.SaveDirectChannel(channel, cm1, cm2)
   479  }
   480  
   481  func (s SqlChannelStore) SaveDirectChannel(directchannel *model.Channel, member1 *model.ChannelMember, member2 *model.ChannelMember) store.StoreChannel {
   482  	return store.Do(func(result *store.StoreResult) {
   483  		if directchannel.DeleteAt != 0 {
   484  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest)
   485  			return
   486  		}
   487  
   488  		if directchannel.Type != model.CHANNEL_DIRECT {
   489  			result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.not_direct.app_error", nil, "", http.StatusBadRequest)
   490  			return
   491  		}
   492  
   493  		transaction, err := s.GetMaster().Begin()
   494  		if err != nil {
   495  			result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   496  			return
   497  		}
   498  		defer finalizeTransaction(transaction)
   499  
   500  		directchannel.TeamId = ""
   501  		channelResult := s.saveChannelT(transaction, directchannel, 0)
   502  
   503  		if channelResult.Err != nil {
   504  			result.Err = channelResult.Err
   505  			result.Data = channelResult.Data
   506  			return
   507  		}
   508  
   509  		newChannel := channelResult.Data.(*model.Channel)
   510  		// Members need new channel ID
   511  		member1.ChannelId = newChannel.Id
   512  		member2.ChannelId = newChannel.Id
   513  
   514  		member1Result := s.saveMemberT(transaction, member1, newChannel)
   515  		member2Result := member1Result
   516  		if member1.UserId != member2.UserId {
   517  			member2Result = s.saveMemberT(transaction, member2, newChannel)
   518  		}
   519  
   520  		if member1Result.Err != nil || member2Result.Err != nil {
   521  			details := ""
   522  			if member1Result.Err != nil {
   523  				details += "Member1Err: " + member1Result.Err.Message
   524  			}
   525  			if member2Result.Err != nil {
   526  				details += "Member2Err: " + member2Result.Err.Message
   527  			}
   528  			result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.add_members.app_error", nil, details, http.StatusInternalServerError)
   529  			return
   530  		}
   531  
   532  		if err := transaction.Commit(); err != nil {
   533  			result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.commit.app_error", nil, err.Error(), http.StatusInternalServerError)
   534  			return
   535  		}
   536  
   537  		*result = channelResult
   538  	})
   539  }
   540  
   541  func (s SqlChannelStore) saveChannelT(transaction *gorp.Transaction, channel *model.Channel, maxChannelsPerTeam int64) store.StoreResult {
   542  	result := store.StoreResult{}
   543  
   544  	if len(channel.Id) > 0 {
   545  		result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.existing.app_error", nil, "id="+channel.Id, http.StatusBadRequest)
   546  		return result
   547  	}
   548  
   549  	channel.PreSave()
   550  	if result.Err = channel.IsValid(); result.Err != nil {
   551  		return result
   552  	}
   553  
   554  	if channel.Type != model.CHANNEL_DIRECT && channel.Type != model.CHANNEL_GROUP && maxChannelsPerTeam >= 0 {
   555  		if count, err := transaction.SelectInt("SELECT COUNT(0) FROM Channels WHERE TeamId = :TeamId AND DeleteAt = 0 AND (Type = 'O' OR Type = 'P')", map[string]interface{}{"TeamId": channel.TeamId}); err != nil {
   556  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.current_count.app_error", nil, "teamId="+channel.TeamId+", "+err.Error(), http.StatusInternalServerError)
   557  			return result
   558  		} else if count >= maxChannelsPerTeam {
   559  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.limit.app_error", nil, "teamId="+channel.TeamId, http.StatusBadRequest)
   560  			return result
   561  		}
   562  	}
   563  
   564  	if err := transaction.Insert(channel); err != nil {
   565  		if IsUniqueConstraintError(err, []string{"Name", "channels_name_teamid_key"}) {
   566  			dupChannel := model.Channel{}
   567  			s.GetMaster().SelectOne(&dupChannel, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Name = :Name", map[string]interface{}{"TeamId": channel.TeamId, "Name": channel.Name})
   568  			if dupChannel.DeleteAt > 0 {
   569  				result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.previously.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest)
   570  			} else {
   571  				result.Err = model.NewAppError("SqlChannelStore.Save", store.CHANNEL_EXISTS_ERROR, nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest)
   572  				result.Data = &dupChannel
   573  			}
   574  		} else {
   575  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.save.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusInternalServerError)
   576  		}
   577  	} else {
   578  		result.Data = channel
   579  	}
   580  
   581  	return result
   582  }
   583  
   584  // Update writes the updated channel to the database.
   585  func (s SqlChannelStore) Update(channel *model.Channel) store.StoreChannel {
   586  	return store.Do(func(result *store.StoreResult) {
   587  		transaction, err := s.GetMaster().Begin()
   588  		if err != nil {
   589  			result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   590  			return
   591  		}
   592  		defer finalizeTransaction(transaction)
   593  
   594  		*result = s.updateChannelT(transaction, channel)
   595  		if result.Err != nil {
   596  			return
   597  		}
   598  
   599  		// Additionally propagate the write to the PublicChannels table.
   600  		if err := s.upsertPublicChannelT(transaction, result.Data.(*model.Channel)); err != nil {
   601  			result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.upsert_public_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
   602  			return
   603  		}
   604  
   605  		if err := transaction.Commit(); err != nil {
   606  			result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   607  			return
   608  		}
   609  	})
   610  
   611  }
   612  
   613  func (s SqlChannelStore) updateChannelT(transaction *gorp.Transaction, channel *model.Channel) store.StoreResult {
   614  	result := store.StoreResult{}
   615  
   616  	channel.PreUpdate()
   617  
   618  	if channel.DeleteAt != 0 {
   619  		result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.archived_channel.app_error", nil, "", http.StatusBadRequest)
   620  		return result
   621  	}
   622  
   623  	if result.Err = channel.IsValid(); result.Err != nil {
   624  		return result
   625  	}
   626  
   627  	count, err := transaction.Update(channel)
   628  	if err != nil {
   629  		if IsUniqueConstraintError(err, []string{"Name", "channels_name_teamid_key"}) {
   630  			dupChannel := model.Channel{}
   631  			s.GetReplica().SelectOne(&dupChannel, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Name= :Name AND DeleteAt > 0", map[string]interface{}{"TeamId": channel.TeamId, "Name": channel.Name})
   632  			if dupChannel.DeleteAt > 0 {
   633  				result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.previously.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest)
   634  				return result
   635  			}
   636  			result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.exists.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest)
   637  			return result
   638  		}
   639  		result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.updating.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusInternalServerError)
   640  		return result
   641  	}
   642  
   643  	if count != 1 {
   644  		result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.app_error", nil, "id="+channel.Id, http.StatusInternalServerError)
   645  		return result
   646  	}
   647  
   648  	result.Data = channel
   649  
   650  	return result
   651  }
   652  
   653  func (s SqlChannelStore) GetChannelUnread(channelId, userId string) store.StoreChannel {
   654  	return store.Do(func(result *store.StoreResult) {
   655  		var unreadChannel model.ChannelUnread
   656  		err := s.GetReplica().SelectOne(&unreadChannel,
   657  			`SELECT
   658  				Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps
   659  			FROM
   660  				Channels, ChannelMembers
   661  			WHERE
   662  				Id = ChannelId
   663                  AND Id = :ChannelId
   664                  AND UserId = :UserId
   665                  AND DeleteAt = 0`,
   666  			map[string]interface{}{"ChannelId": channelId, "UserId": userId})
   667  
   668  		if err != nil {
   669  			result.Err = model.NewAppError("SqlChannelStore.GetChannelUnread", "store.sql_channel.get_unread.app_error", nil, "channelId="+channelId+" "+err.Error(), http.StatusInternalServerError)
   670  			if err == sql.ErrNoRows {
   671  				result.Err.StatusCode = http.StatusNotFound
   672  			}
   673  		} else {
   674  			result.Data = &unreadChannel
   675  		}
   676  	})
   677  }
   678  
   679  func (s SqlChannelStore) InvalidateChannel(id string) {
   680  	channelCache.Remove(id)
   681  	if s.metrics != nil {
   682  		s.metrics.IncrementMemCacheInvalidationCounter("Channel - Remove by ChannelId")
   683  	}
   684  }
   685  
   686  func (s SqlChannelStore) InvalidateChannelByName(teamId, name string) {
   687  	channelByNameCache.Remove(teamId + name)
   688  	if s.metrics != nil {
   689  		s.metrics.IncrementMemCacheInvalidationCounter("Channel by Name - Remove by TeamId and Name")
   690  	}
   691  }
   692  
   693  func (s SqlChannelStore) Get(id string, allowFromCache bool) store.StoreChannel {
   694  	return s.get(id, false, allowFromCache)
   695  }
   696  
   697  func (s SqlChannelStore) GetPinnedPosts(channelId string) store.StoreChannel {
   698  	return store.Do(func(result *store.StoreResult) {
   699  		pl := model.NewPostList()
   700  
   701  		var posts []*model.Post
   702  		if _, err := s.GetReplica().Select(&posts, "SELECT * FROM Posts WHERE IsPinned = true AND ChannelId = :ChannelId AND DeleteAt = 0 ORDER BY CreateAt ASC", map[string]interface{}{"ChannelId": channelId}); err != nil {
   703  			result.Err = model.NewAppError("SqlPostStore.GetPinnedPosts", "store.sql_channel.pinned_posts.app_error", nil, err.Error(), http.StatusInternalServerError)
   704  		} else {
   705  			for _, post := range posts {
   706  				pl.AddPost(post)
   707  				pl.AddOrder(post.Id)
   708  			}
   709  		}
   710  
   711  		result.Data = pl
   712  	})
   713  }
   714  
   715  func (s SqlChannelStore) GetFromMaster(id string) store.StoreChannel {
   716  	return s.get(id, true, false)
   717  }
   718  
   719  func (s SqlChannelStore) get(id string, master bool, allowFromCache bool) store.StoreChannel {
   720  	return store.Do(func(result *store.StoreResult) {
   721  		var db *gorp.DbMap
   722  		if master {
   723  			db = s.GetMaster()
   724  		} else {
   725  			db = s.GetReplica()
   726  		}
   727  
   728  		if allowFromCache {
   729  			if cacheItem, ok := channelCache.Get(id); ok {
   730  				if s.metrics != nil {
   731  					s.metrics.IncrementMemCacheHitCounter("Channel")
   732  				}
   733  				result.Data = (cacheItem.(*model.Channel)).DeepCopy()
   734  				return
   735  			}
   736  		}
   737  
   738  		if s.metrics != nil {
   739  			s.metrics.IncrementMemCacheMissCounter("Channel")
   740  		}
   741  
   742  		obj, err := db.Get(model.Channel{}, id)
   743  		if err != nil {
   744  			result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.find.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError)
   745  			return
   746  		}
   747  
   748  		if obj == nil {
   749  			result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.existing.app_error", nil, "id="+id, http.StatusNotFound)
   750  			return
   751  		}
   752  
   753  		result.Data = obj.(*model.Channel)
   754  		channelCache.AddWithExpiresInSecs(id, obj.(*model.Channel), CHANNEL_CACHE_SEC)
   755  	})
   756  }
   757  
   758  // Delete records the given deleted timestamp to the channel in question.
   759  func (s SqlChannelStore) Delete(channelId string, time int64) store.StoreChannel {
   760  	return s.SetDeleteAt(channelId, time, time)
   761  }
   762  
   763  // Restore reverts a previous deleted timestamp from the channel in question.
   764  func (s SqlChannelStore) Restore(channelId string, time int64) store.StoreChannel {
   765  	return s.SetDeleteAt(channelId, 0, time)
   766  }
   767  
   768  // SetDeleteAt records the given deleted and updated timestamp to the channel in question.
   769  func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64) store.StoreChannel {
   770  	return store.Do(func(result *store.StoreResult) {
   771  		defer s.InvalidateChannel(channelId)
   772  
   773  		transaction, err := s.GetMaster().Begin()
   774  		if err != nil {
   775  			result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   776  			return
   777  		}
   778  		defer finalizeTransaction(transaction)
   779  
   780  		*result = s.setDeleteAtT(transaction, channelId, deleteAt, updateAt)
   781  		if result.Err != nil {
   782  			return
   783  		}
   784  
   785  		// Additionally propagate the write to the PublicChannels table.
   786  		if _, err := transaction.Exec(`
   787  			UPDATE
   788  			    PublicChannels
   789  			SET
   790  			    DeleteAt = :DeleteAt
   791  			WHERE
   792  			    Id = :ChannelId
   793  		`, map[string]interface{}{
   794  			"DeleteAt":  deleteAt,
   795  			"ChannelId": channelId,
   796  		}); err != nil {
   797  			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)
   798  			return
   799  		}
   800  
   801  		if err := transaction.Commit(); err != nil {
   802  			result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   803  			return
   804  		}
   805  	})
   806  }
   807  
   808  func (s SqlChannelStore) setDeleteAtT(transaction *gorp.Transaction, channelId string, deleteAt, updateAt int64) store.StoreResult {
   809  	result := store.StoreResult{}
   810  
   811  	_, err := transaction.Exec("Update Channels SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :ChannelId", map[string]interface{}{"DeleteAt": deleteAt, "UpdateAt": updateAt, "ChannelId": channelId})
   812  	if err != nil {
   813  		result.Err = model.NewAppError("SqlChannelStore.Delete", "store.sql_channel.delete.channel.app_error", nil, "id="+channelId+", err="+err.Error(), http.StatusInternalServerError)
   814  		return result
   815  	}
   816  
   817  	return result
   818  }
   819  
   820  // PermanentDeleteByTeam removes all channels for the given team from the database.
   821  func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) store.StoreChannel {
   822  	return store.Do(func(result *store.StoreResult) {
   823  		transaction, err := s.GetMaster().Begin()
   824  		if err != nil {
   825  			result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   826  			return
   827  		}
   828  		defer finalizeTransaction(transaction)
   829  
   830  		*result = s.permanentDeleteByTeamtT(transaction, teamId)
   831  		if result.Err != nil {
   832  			return
   833  		}
   834  
   835  		// Additionally propagate the deletions to the PublicChannels table.
   836  		if _, err := transaction.Exec(`
   837  			DELETE FROM
   838  			    PublicChannels
   839  			WHERE
   840  			    TeamId = :TeamId
   841  		`, map[string]interface{}{
   842  			"TeamId": teamId,
   843  		}); err != nil {
   844  			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)
   845  			return
   846  		}
   847  
   848  		if err := transaction.Commit(); err != nil {
   849  			result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   850  			return
   851  		}
   852  	})
   853  }
   854  
   855  func (s SqlChannelStore) permanentDeleteByTeamtT(transaction *gorp.Transaction, teamId string) store.StoreResult {
   856  	result := store.StoreResult{}
   857  
   858  	if _, err := transaction.Exec("DELETE FROM Channels WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
   859  		result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError)
   860  		return result
   861  	}
   862  
   863  	return result
   864  }
   865  
   866  // PermanentDelete removes the given channel from the database.
   867  func (s SqlChannelStore) PermanentDelete(channelId string) store.StoreChannel {
   868  	return store.Do(func(result *store.StoreResult) {
   869  		transaction, err := s.GetMaster().Begin()
   870  		if err != nil {
   871  			result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   872  			return
   873  		}
   874  		defer finalizeTransaction(transaction)
   875  
   876  		*result = s.permanentDeleteT(transaction, channelId)
   877  		if result.Err != nil {
   878  			return
   879  		}
   880  
   881  		// Additionally propagate the deletion to the PublicChannels table.
   882  		if _, err := transaction.Exec(`
   883  			DELETE FROM
   884  			    PublicChannels
   885  			WHERE
   886  			    Id = :ChannelId
   887  		`, map[string]interface{}{
   888  			"ChannelId": channelId,
   889  		}); err != nil {
   890  			result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.delete_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
   891  			return
   892  		}
   893  
   894  		if err := transaction.Commit(); err != nil {
   895  			result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   896  			return
   897  		}
   898  	})
   899  }
   900  
   901  func (s SqlChannelStore) permanentDeleteT(transaction *gorp.Transaction, channelId string) store.StoreResult {
   902  	result := store.StoreResult{}
   903  
   904  	if _, err := transaction.Exec("DELETE FROM Channels WHERE Id = :ChannelId", map[string]interface{}{"ChannelId": channelId}); err != nil {
   905  		result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
   906  		return result
   907  	}
   908  
   909  	return result
   910  }
   911  
   912  func (s SqlChannelStore) PermanentDeleteMembersByChannel(channelId string) store.StoreChannel {
   913  	return store.Do(func(result *store.StoreResult) {
   914  		_, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId", map[string]interface{}{"ChannelId": channelId})
   915  		if err != nil {
   916  			result.Err = model.NewAppError("SqlChannelStore.RemoveAllMembersByChannel", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
   917  		}
   918  	})
   919  }
   920  
   921  func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDeleted bool) store.StoreChannel {
   922  	return store.Do(func(result *store.StoreResult) {
   923  		query := "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND DeleteAt = 0 AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName"
   924  		if includeDeleted {
   925  			query = "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName"
   926  		}
   927  		data := &model.ChannelList{}
   928  		_, err := s.GetReplica().Select(data, query, map[string]interface{}{"TeamId": teamId, "UserId": userId})
   929  
   930  		if err != nil {
   931  			result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
   932  			return
   933  		}
   934  
   935  		if len(*data) == 0 {
   936  			result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.not_found.app_error", nil, "teamId="+teamId+", userId="+userId, http.StatusBadRequest)
   937  			return
   938  		}
   939  
   940  		result.Data = data
   941  	})
   942  }
   943  
   944  func (s SqlChannelStore) GetAllChannels(offset int, limit int, includeDeleted bool) store.StoreChannel {
   945  	return store.Do(func(result *store.StoreResult) {
   946  		deleteFilter := "AND c.DeleteAt = 0"
   947  		if includeDeleted {
   948  			deleteFilter = ""
   949  		}
   950  
   951  		query := "SELECT c.*, Teams.DisplayName AS TeamDisplayName, Teams.Name AS TeamName, Teams.UpdateAt as TeamUpdateAt FROM Channels AS c JOIN Teams ON Teams.Id = c.TeamId WHERE (c.Type = 'P' OR c.Type = 'O') " + deleteFilter + " ORDER BY c.DisplayName, Teams.DisplayName LIMIT :Limit OFFSET :Offset"
   952  
   953  		data := &model.ChannelListWithTeamData{}
   954  		_, err := s.GetReplica().Select(data, query, map[string]interface{}{"Limit": limit, "Offset": offset})
   955  
   956  		if err != nil {
   957  			result.Err = model.NewAppError("SqlChannelStore.GetAllChannels", "store.sql_channel.get_all_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
   958  			return
   959  		}
   960  
   961  		result.Data = data
   962  	})
   963  }
   964  
   965  func (s SqlChannelStore) GetMoreChannels(teamId string, userId string, offset int, limit int) store.StoreChannel {
   966  	return store.Do(func(result *store.StoreResult) {
   967  		data := &model.ChannelList{}
   968  		_, err := s.GetReplica().Select(data, `
   969  			SELECT
   970  			    Channels.*
   971  			FROM
   972  			    Channels
   973  			JOIN
   974  			    PublicChannels c ON (c.Id = Channels.Id)
   975  			WHERE
   976  			    c.TeamId = :TeamId
   977  			AND c.DeleteAt = 0
   978  			AND c.Id NOT IN (
   979  			    SELECT
   980  			        c.Id
   981  			    FROM
   982  			        PublicChannels c
   983  			    JOIN
   984  			        ChannelMembers cm ON (cm.ChannelId = c.Id)
   985  			    WHERE
   986  			        c.TeamId = :TeamId
   987  			    AND cm.UserId = :UserId
   988  			    AND c.DeleteAt = 0
   989  			)
   990  			ORDER BY
   991  				c.DisplayName
   992  			LIMIT :Limit
   993  			OFFSET :Offset
   994  		`, map[string]interface{}{
   995  			"TeamId": teamId,
   996  			"UserId": userId,
   997  			"Limit":  limit,
   998  			"Offset": offset,
   999  		})
  1000  
  1001  		if err != nil {
  1002  			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)
  1003  			return
  1004  		}
  1005  
  1006  		result.Data = data
  1007  	})
  1008  }
  1009  
  1010  func (s SqlChannelStore) GetPublicChannelsForTeam(teamId string, offset int, limit int) store.StoreChannel {
  1011  	return store.Do(func(result *store.StoreResult) {
  1012  		data := &model.ChannelList{}
  1013  		_, err := s.GetReplica().Select(data, `
  1014  			SELECT
  1015  			    Channels.*
  1016  			FROM
  1017  			    Channels
  1018  			JOIN
  1019  			    PublicChannels pc ON (pc.Id = Channels.Id)
  1020  			WHERE
  1021  			    pc.TeamId = :TeamId
  1022  			AND pc.DeleteAt = 0
  1023  			ORDER BY pc.DisplayName
  1024  			LIMIT :Limit
  1025  			OFFSET :Offset
  1026  		`, map[string]interface{}{
  1027  			"TeamId": teamId,
  1028  			"Limit":  limit,
  1029  			"Offset": offset,
  1030  		})
  1031  
  1032  		if err != nil {
  1033  			result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsForTeam", "store.sql_channel.get_public_channels.get.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError)
  1034  			return
  1035  		}
  1036  
  1037  		result.Data = data
  1038  	})
  1039  }
  1040  
  1041  func (s SqlChannelStore) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) store.StoreChannel {
  1042  	return store.Do(func(result *store.StoreResult) {
  1043  		props := make(map[string]interface{})
  1044  		props["teamId"] = teamId
  1045  
  1046  		idQuery := ""
  1047  
  1048  		for index, channelId := range channelIds {
  1049  			if len(idQuery) > 0 {
  1050  				idQuery += ", "
  1051  			}
  1052  
  1053  			props["channelId"+strconv.Itoa(index)] = channelId
  1054  			idQuery += ":channelId" + strconv.Itoa(index)
  1055  		}
  1056  
  1057  		data := &model.ChannelList{}
  1058  		_, err := s.GetReplica().Select(data, `
  1059  			SELECT
  1060  			    Channels.*
  1061  			FROM
  1062  			    Channels
  1063  			JOIN
  1064  			    PublicChannels pc ON (pc.Id = Channels.Id)
  1065  			WHERE
  1066  			    pc.TeamId = :teamId
  1067  			AND pc.DeleteAt = 0
  1068  			AND pc.Id IN (`+idQuery+`)
  1069  			ORDER BY pc.DisplayName
  1070  		`, props)
  1071  
  1072  		if err != nil {
  1073  			result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1074  		}
  1075  
  1076  		if len(*data) == 0 {
  1077  			result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.not_found.app_error", nil, "", http.StatusNotFound)
  1078  		}
  1079  
  1080  		result.Data = data
  1081  	})
  1082  }
  1083  
  1084  type channelIdWithCountAndUpdateAt struct {
  1085  	Id            string
  1086  	TotalMsgCount int64
  1087  	UpdateAt      int64
  1088  }
  1089  
  1090  func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) store.StoreChannel {
  1091  	return store.Do(func(result *store.StoreResult) {
  1092  		var data []channelIdWithCountAndUpdateAt
  1093  		_, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND (TeamId = :TeamId OR TeamId = '') AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId})
  1094  
  1095  		if err != nil {
  1096  			result.Err = model.NewAppError("SqlChannelStore.GetChannelCounts", "store.sql_channel.get_channel_counts.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  1097  			return
  1098  		}
  1099  
  1100  		counts := &model.ChannelCounts{Counts: make(map[string]int64), UpdateTimes: make(map[string]int64)}
  1101  		for i := range data {
  1102  			v := data[i]
  1103  			counts.Counts[v.Id] = v.TotalMsgCount
  1104  			counts.UpdateTimes[v.Id] = v.UpdateAt
  1105  		}
  1106  
  1107  		result.Data = counts
  1108  	})
  1109  }
  1110  
  1111  func (s SqlChannelStore) GetTeamChannels(teamId string) store.StoreChannel {
  1112  	return store.Do(func(result *store.StoreResult) {
  1113  		data := &model.ChannelList{}
  1114  		_, err := s.GetReplica().Select(data, "SELECT * FROM Channels WHERE TeamId = :TeamId And Type != 'D' ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId})
  1115  
  1116  		if err != nil {
  1117  			result.Err = model.NewAppError("SqlChannelStore.GetTeamChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+",  err="+err.Error(), http.StatusInternalServerError)
  1118  			return
  1119  		}
  1120  
  1121  		if len(*data) == 0 {
  1122  			result.Err = model.NewAppError("SqlChannelStore.GetTeamChannels", "store.sql_channel.get_channels.not_found.app_error", nil, "teamId="+teamId, http.StatusNotFound)
  1123  			return
  1124  		}
  1125  
  1126  		result.Data = data
  1127  	})
  1128  }
  1129  
  1130  func (s SqlChannelStore) GetByName(teamId string, name string, allowFromCache bool) store.StoreChannel {
  1131  	return s.getByName(teamId, name, false, allowFromCache)
  1132  }
  1133  
  1134  func (s SqlChannelStore) GetByNames(teamId string, names []string, allowFromCache bool) store.StoreChannel {
  1135  	return store.Do(func(result *store.StoreResult) {
  1136  		var channels []*model.Channel
  1137  
  1138  		if allowFromCache {
  1139  			var misses []string
  1140  			visited := make(map[string]struct{})
  1141  			for _, name := range names {
  1142  				if _, ok := visited[name]; ok {
  1143  					continue
  1144  				}
  1145  				visited[name] = struct{}{}
  1146  				if cacheItem, ok := channelByNameCache.Get(teamId + name); ok {
  1147  					if s.metrics != nil {
  1148  						s.metrics.IncrementMemCacheHitCounter("Channel By Name")
  1149  					}
  1150  					channels = append(channels, cacheItem.(*model.Channel))
  1151  				} else {
  1152  					if s.metrics != nil {
  1153  						s.metrics.IncrementMemCacheMissCounter("Channel By Name")
  1154  					}
  1155  					misses = append(misses, name)
  1156  				}
  1157  			}
  1158  			names = misses
  1159  		}
  1160  
  1161  		if len(names) > 0 {
  1162  			props := map[string]interface{}{}
  1163  			var namePlaceholders []string
  1164  			for _, name := range names {
  1165  				key := fmt.Sprintf("Name%v", len(namePlaceholders))
  1166  				props[key] = name
  1167  				namePlaceholders = append(namePlaceholders, ":"+key)
  1168  			}
  1169  
  1170  			var query string
  1171  			if teamId == "" {
  1172  				query = `SELECT * FROM Channels WHERE Name IN (` + strings.Join(namePlaceholders, ", ") + `) AND DeleteAt = 0`
  1173  			} else {
  1174  				props["TeamId"] = teamId
  1175  				query = `SELECT * FROM Channels WHERE Name IN (` + strings.Join(namePlaceholders, ", ") + `) AND TeamId = :TeamId AND DeleteAt = 0`
  1176  			}
  1177  
  1178  			var dbChannels []*model.Channel
  1179  			if _, err := s.GetReplica().Select(&dbChannels, query, props); err != nil && err != sql.ErrNoRows {
  1180  				result.Err = model.NewAppError("SqlChannelStore.GetByName", "store.sql_channel.get_by_name.existing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError)
  1181  				return
  1182  			}
  1183  			for _, channel := range dbChannels {
  1184  				channelByNameCache.AddWithExpiresInSecs(teamId+channel.Name, channel, CHANNEL_CACHE_SEC)
  1185  				channels = append(channels, channel)
  1186  			}
  1187  		}
  1188  
  1189  		result.Data = channels
  1190  	})
  1191  }
  1192  
  1193  func (s SqlChannelStore) GetByNameIncludeDeleted(teamId string, name string, allowFromCache bool) store.StoreChannel {
  1194  	return s.getByName(teamId, name, true, allowFromCache)
  1195  }
  1196  
  1197  func (s SqlChannelStore) getByName(teamId string, name string, includeDeleted bool, allowFromCache bool) store.StoreChannel {
  1198  	var query string
  1199  	if includeDeleted {
  1200  		query = "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name"
  1201  	} else {
  1202  		query = "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt = 0"
  1203  	}
  1204  	return store.Do(func(result *store.StoreResult) {
  1205  		channel := model.Channel{}
  1206  
  1207  		if allowFromCache {
  1208  			if cacheItem, ok := channelByNameCache.Get(teamId + name); ok {
  1209  				if s.metrics != nil {
  1210  					s.metrics.IncrementMemCacheHitCounter("Channel By Name")
  1211  				}
  1212  				result.Data = cacheItem.(*model.Channel)
  1213  				return
  1214  			}
  1215  			if s.metrics != nil {
  1216  				s.metrics.IncrementMemCacheMissCounter("Channel By Name")
  1217  			}
  1218  		}
  1219  
  1220  		if err := s.GetReplica().SelectOne(&channel, query, map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil {
  1221  			if err == sql.ErrNoRows {
  1222  				result.Err = model.NewAppError("SqlChannelStore.GetByName", store.MISSING_CHANNEL_ERROR, nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusNotFound)
  1223  				return
  1224  			}
  1225  			result.Err = model.NewAppError("SqlChannelStore.GetByName", "store.sql_channel.get_by_name.existing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusInternalServerError)
  1226  			return
  1227  		}
  1228  
  1229  		result.Data = &channel
  1230  		channelByNameCache.AddWithExpiresInSecs(teamId+name, &channel, CHANNEL_CACHE_SEC)
  1231  	})
  1232  }
  1233  
  1234  func (s SqlChannelStore) GetDeletedByName(teamId string, name string) store.StoreChannel {
  1235  	return store.Do(func(result *store.StoreResult) {
  1236  		channel := model.Channel{}
  1237  
  1238  		if err := s.GetReplica().SelectOne(&channel, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt != 0", map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil {
  1239  			if err == sql.ErrNoRows {
  1240  				result.Err = model.NewAppError("SqlChannelStore.GetDeletedByName", "store.sql_channel.get_deleted_by_name.missing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusNotFound)
  1241  				return
  1242  			}
  1243  			result.Err = model.NewAppError("SqlChannelStore.GetDeletedByName", "store.sql_channel.get_deleted_by_name.existing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusInternalServerError)
  1244  			return
  1245  		}
  1246  
  1247  		result.Data = &channel
  1248  	})
  1249  }
  1250  
  1251  func (s SqlChannelStore) GetDeleted(teamId string, offset int, limit int) store.StoreChannel {
  1252  	return store.Do(func(result *store.StoreResult) {
  1253  		channels := &model.ChannelList{}
  1254  
  1255  		if _, err := s.GetReplica().Select(channels, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND DeleteAt != 0 ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset}); err != nil {
  1256  			if err == sql.ErrNoRows {
  1257  				result.Err = model.NewAppError("SqlChannelStore.GetDeleted", "store.sql_channel.get_deleted.missing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusNotFound)
  1258  				return
  1259  			}
  1260  			result.Err = model.NewAppError("SqlChannelStore.GetDeleted", "store.sql_channel.get_deleted.existing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError)
  1261  			return
  1262  		}
  1263  
  1264  		result.Data = channels
  1265  	})
  1266  }
  1267  
  1268  var CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY = `
  1269  	SELECT
  1270  		ChannelMembers.*,
  1271  		TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1272  		TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1273  		ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1274  		ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1275  	FROM
  1276  		ChannelMembers
  1277  	INNER JOIN
  1278  		Channels ON ChannelMembers.ChannelId = Channels.Id
  1279  	LEFT JOIN
  1280  		Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
  1281  	LEFT JOIN
  1282  		Teams ON Channels.TeamId = Teams.Id
  1283  	LEFT JOIN
  1284  		Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
  1285  `
  1286  
  1287  func (s SqlChannelStore) SaveMember(member *model.ChannelMember) store.StoreChannel {
  1288  	return store.Do(func(result *store.StoreResult) {
  1289  		defer s.InvalidateAllChannelMembersForUser(member.UserId)
  1290  
  1291  		// Grab the channel we are saving this member to
  1292  		cr := <-s.GetFromMaster(member.ChannelId)
  1293  		if cr.Err != nil {
  1294  			result.Err = cr.Err
  1295  			return
  1296  		}
  1297  
  1298  		channel := cr.Data.(*model.Channel)
  1299  
  1300  		transaction, err := s.GetMaster().Begin()
  1301  		if err != nil {
  1302  			result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  1303  			return
  1304  		}
  1305  		defer finalizeTransaction(transaction)
  1306  
  1307  		*result = s.saveMemberT(transaction, member, channel)
  1308  		if result.Err != nil {
  1309  			return
  1310  		}
  1311  
  1312  		if err := transaction.Commit(); err != nil {
  1313  			result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  1314  			return
  1315  		}
  1316  	})
  1317  }
  1318  
  1319  func (s SqlChannelStore) saveMemberT(transaction *gorp.Transaction, member *model.ChannelMember, channel *model.Channel) store.StoreResult {
  1320  	result := store.StoreResult{}
  1321  
  1322  	member.PreSave()
  1323  	if result.Err = member.IsValid(); result.Err != nil {
  1324  		return result
  1325  	}
  1326  
  1327  	dbMember := NewChannelMemberFromModel(member)
  1328  
  1329  	if err := transaction.Insert(dbMember); err != nil {
  1330  		if IsUniqueConstraintError(err, []string{"ChannelId", "channelmembers_pkey"}) {
  1331  			result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.exists.app_error", nil, "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest)
  1332  			return result
  1333  		}
  1334  		result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.save.app_error", nil, "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
  1335  		return result
  1336  	}
  1337  
  1338  	var retrievedMember channelMemberWithSchemeRoles
  1339  	if err := transaction.SelectOne(&retrievedMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": dbMember.ChannelId, "UserId": dbMember.UserId}); err != nil {
  1340  		if err == sql.ErrNoRows {
  1341  			result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+dbMember.ChannelId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound)
  1342  			return result
  1343  		}
  1344  		result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+dbMember.ChannelId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusInternalServerError)
  1345  		return result
  1346  	}
  1347  
  1348  	result.Data = retrievedMember.ToModel()
  1349  	return result
  1350  }
  1351  
  1352  func (s SqlChannelStore) UpdateMember(member *model.ChannelMember) store.StoreChannel {
  1353  	return store.Do(func(result *store.StoreResult) {
  1354  		member.PreUpdate()
  1355  
  1356  		if result.Err = member.IsValid(); result.Err != nil {
  1357  			return
  1358  		}
  1359  
  1360  		if _, err := s.GetMaster().Update(NewChannelMemberFromModel(member)); err != nil {
  1361  			result.Err = model.NewAppError("SqlChannelStore.UpdateMember", "store.sql_channel.update_member.app_error", nil, "channel_id="+member.ChannelId+", "+"user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
  1362  			return
  1363  		}
  1364  
  1365  		var dbMember channelMemberWithSchemeRoles
  1366  
  1367  		if err := s.GetReplica().SelectOne(&dbMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
  1368  			if err == sql.ErrNoRows {
  1369  				result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound)
  1370  				return
  1371  			}
  1372  			result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError)
  1373  			return
  1374  		}
  1375  		result.Data = dbMember.ToModel()
  1376  	})
  1377  }
  1378  
  1379  func (s SqlChannelStore) GetMembers(channelId string, offset, limit int) store.StoreChannel {
  1380  	return store.Do(func(result *store.StoreResult) {
  1381  		var dbMembers channelMemberWithSchemeRolesList
  1382  		_, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelId = :ChannelId LIMIT :Limit OFFSET :Offset", map[string]interface{}{"ChannelId": channelId, "Limit": limit, "Offset": offset})
  1383  		if err != nil {
  1384  			result.Err = model.NewAppError("SqlChannelStore.GetMembers", "store.sql_channel.get_members.app_error", nil, "channel_id="+channelId+","+err.Error(), http.StatusInternalServerError)
  1385  			return
  1386  		}
  1387  
  1388  		result.Data = dbMembers.ToModel()
  1389  	})
  1390  }
  1391  
  1392  func (s SqlChannelStore) GetChannelMembersTimezones(channelId string) store.StoreChannel {
  1393  	return store.Do(func(result *store.StoreResult) {
  1394  		var dbMembersTimezone []map[string]string
  1395  		_, err := s.GetReplica().Select(&dbMembersTimezone, `
  1396  					SELECT
  1397  						Users.Timezone
  1398  					FROM
  1399  						ChannelMembers
  1400  					LEFT JOIN
  1401  						Users  ON ChannelMembers.UserId = Id
  1402  					WHERE ChannelId = :ChannelId
  1403  		`, map[string]interface{}{
  1404  			"ChannelId": channelId})
  1405  		if err != nil {
  1406  			result.Err = model.NewAppError("SqlChannelStore.GetChannelMembersTimezones", "store.sql_channel.get_members.app_error", nil, "channel_id="+channelId+","+err.Error(), http.StatusInternalServerError)
  1407  			return
  1408  		}
  1409  		result.Data = dbMembersTimezone
  1410  	})
  1411  }
  1412  
  1413  func (s SqlChannelStore) GetMember(channelId string, userId string) store.StoreChannel {
  1414  	return store.Do(func(result *store.StoreResult) {
  1415  		var dbMember channelMemberWithSchemeRoles
  1416  
  1417  		if err := s.GetReplica().SelectOne(&dbMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil {
  1418  			if err == sql.ErrNoRows {
  1419  				result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+channelId+"user_id="+userId+","+err.Error(), http.StatusNotFound)
  1420  				return
  1421  			}
  1422  			result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+channelId+"user_id="+userId+","+err.Error(), http.StatusInternalServerError)
  1423  			return
  1424  		}
  1425  
  1426  		result.Data = dbMember.ToModel()
  1427  	})
  1428  }
  1429  
  1430  func (s SqlChannelStore) InvalidateAllChannelMembersForUser(userId string) {
  1431  	allChannelMembersForUserCache.Remove(userId)
  1432  	allChannelMembersForUserCache.Remove(userId + "_deleted")
  1433  	if s.metrics != nil {
  1434  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Remove by UserId")
  1435  	}
  1436  }
  1437  
  1438  func (s SqlChannelStore) IsUserInChannelUseCache(userId string, channelId string) bool {
  1439  	if cacheItem, ok := allChannelMembersForUserCache.Get(userId); ok {
  1440  		if s.metrics != nil {
  1441  			s.metrics.IncrementMemCacheHitCounter("All Channel Members for User")
  1442  		}
  1443  		ids := cacheItem.(map[string]string)
  1444  		if _, ok := ids[channelId]; ok {
  1445  			return true
  1446  		}
  1447  		return false
  1448  	}
  1449  
  1450  	if s.metrics != nil {
  1451  		s.metrics.IncrementMemCacheMissCounter("All Channel Members for User")
  1452  	}
  1453  
  1454  	result := <-s.GetAllChannelMembersForUser(userId, true, false)
  1455  	if result.Err != nil {
  1456  		mlog.Error("SqlChannelStore.IsUserInChannelUseCache: " + result.Err.Error())
  1457  		return false
  1458  	}
  1459  
  1460  	ids := result.Data.(map[string]string)
  1461  	if _, ok := ids[channelId]; ok {
  1462  		return true
  1463  	}
  1464  
  1465  	return false
  1466  }
  1467  
  1468  func (s SqlChannelStore) GetMemberForPost(postId string, userId string) store.StoreChannel {
  1469  	return store.Do(func(result *store.StoreResult) {
  1470  		var dbMember channelMemberWithSchemeRoles
  1471  		if err := s.GetReplica().SelectOne(&dbMember,
  1472  			`
  1473  			SELECT
  1474  				ChannelMembers.*,
  1475  				TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1476  				TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1477  				ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1478  				ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1479  			FROM
  1480  				ChannelMembers
  1481  			INNER JOIN
  1482  				Posts ON ChannelMembers.ChannelId = Posts.ChannelId
  1483  			INNER JOIN
  1484  				Channels ON ChannelMembers.ChannelId = Channels.Id
  1485  			LEFT JOIN
  1486  				Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
  1487  			LEFT JOIN
  1488  				Teams ON Channels.TeamId = Teams.Id
  1489  			LEFT JOIN
  1490  				Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
  1491  			WHERE
  1492  				ChannelMembers.UserId = :UserId
  1493  				AND Posts.Id = :PostId`, map[string]interface{}{"UserId": userId, "PostId": postId}); err != nil {
  1494  			result.Err = model.NewAppError("SqlChannelStore.GetMemberForPost", "store.sql_channel.get_member_for_post.app_error", nil, "postId="+postId+", err="+err.Error(), http.StatusInternalServerError)
  1495  			return
  1496  		}
  1497  		result.Data = dbMember.ToModel()
  1498  	})
  1499  }
  1500  
  1501  func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCache bool, includeDeleted bool) store.StoreChannel {
  1502  	return store.Do(func(result *store.StoreResult) {
  1503  		cache_key := userId
  1504  		if includeDeleted {
  1505  			cache_key += "_deleted"
  1506  		}
  1507  		if allowFromCache {
  1508  			if cacheItem, ok := allChannelMembersForUserCache.Get(cache_key); ok {
  1509  				if s.metrics != nil {
  1510  					s.metrics.IncrementMemCacheHitCounter("All Channel Members for User")
  1511  				}
  1512  				result.Data = cacheItem.(map[string]string)
  1513  				return
  1514  			}
  1515  		}
  1516  
  1517  		if s.metrics != nil {
  1518  			s.metrics.IncrementMemCacheMissCounter("All Channel Members for User")
  1519  		}
  1520  
  1521  		var deletedClause string
  1522  		if !includeDeleted {
  1523  			deletedClause = "Channels.DeleteAt = 0 AND"
  1524  		}
  1525  
  1526  		var data allChannelMembers
  1527  		_, err := s.GetReplica().Select(&data, `
  1528  			SELECT
  1529  				ChannelMembers.ChannelId, ChannelMembers.Roles, ChannelMembers.SchemeUser, ChannelMembers.SchemeAdmin,
  1530  				TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1531  				TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1532  				ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1533  				ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1534  			FROM
  1535  				ChannelMembers
  1536  			INNER JOIN
  1537  				Channels ON ChannelMembers.ChannelId = Channels.Id
  1538  			LEFT JOIN
  1539  				Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
  1540  			LEFT JOIN
  1541  				Teams ON Channels.TeamId = Teams.Id
  1542  			LEFT JOIN
  1543  				Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
  1544  			WHERE
  1545  				`+deletedClause+`
  1546  				ChannelMembers.UserId = :UserId`, map[string]interface{}{"UserId": userId})
  1547  
  1548  		if err != nil {
  1549  			result.Err = model.NewAppError("SqlChannelStore.GetAllChannelMembersForUser", "store.sql_channel.get_channels.get.app_error", nil, "userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  1550  			return
  1551  		}
  1552  
  1553  		ids := data.ToMapStringString()
  1554  		result.Data = ids
  1555  
  1556  		if allowFromCache {
  1557  			allChannelMembersForUserCache.AddWithExpiresInSecs(cache_key, ids, ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SEC)
  1558  		}
  1559  	})
  1560  }
  1561  
  1562  func (s SqlChannelStore) InvalidateCacheForChannelMembersNotifyProps(channelId string) {
  1563  	allChannelMembersNotifyPropsForChannelCache.Remove(channelId)
  1564  	if s.metrics != nil {
  1565  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Remove by ChannelId")
  1566  	}
  1567  }
  1568  
  1569  type allChannelMemberNotifyProps struct {
  1570  	UserId      string
  1571  	NotifyProps model.StringMap
  1572  }
  1573  
  1574  func (s SqlChannelStore) GetAllChannelMembersNotifyPropsForChannel(channelId string, allowFromCache bool) store.StoreChannel {
  1575  	return store.Do(func(result *store.StoreResult) {
  1576  		if allowFromCache {
  1577  			if cacheItem, ok := allChannelMembersNotifyPropsForChannelCache.Get(channelId); ok {
  1578  				if s.metrics != nil {
  1579  					s.metrics.IncrementMemCacheHitCounter("All Channel Members Notify Props for Channel")
  1580  				}
  1581  				result.Data = cacheItem.(map[string]model.StringMap)
  1582  				return
  1583  			}
  1584  		}
  1585  
  1586  		if s.metrics != nil {
  1587  			s.metrics.IncrementMemCacheMissCounter("All Channel Members Notify Props for Channel")
  1588  		}
  1589  
  1590  		var data []allChannelMemberNotifyProps
  1591  		_, err := s.GetReplica().Select(&data, `
  1592  			SELECT UserId, NotifyProps
  1593  			FROM ChannelMembers
  1594  			WHERE ChannelId = :ChannelId`, map[string]interface{}{"ChannelId": channelId})
  1595  
  1596  		if err != nil {
  1597  			result.Err = model.NewAppError("SqlChannelStore.GetAllChannelMembersPropsForChannel", "store.sql_channel.get_members.app_error", nil, "channelId="+channelId+", err="+err.Error(), http.StatusInternalServerError)
  1598  			return
  1599  		}
  1600  
  1601  		props := make(map[string]model.StringMap)
  1602  		for i := range data {
  1603  			props[data[i].UserId] = data[i].NotifyProps
  1604  		}
  1605  
  1606  		result.Data = props
  1607  
  1608  		allChannelMembersNotifyPropsForChannelCache.AddWithExpiresInSecs(channelId, props, ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SEC)
  1609  	})
  1610  }
  1611  
  1612  func (s SqlChannelStore) InvalidateMemberCount(channelId string) {
  1613  	channelMemberCountsCache.Remove(channelId)
  1614  	if s.metrics != nil {
  1615  		s.metrics.IncrementMemCacheInvalidationCounter("Channel Member Counts - Remove by ChannelId")
  1616  	}
  1617  }
  1618  
  1619  func (s SqlChannelStore) GetMemberCountFromCache(channelId string) int64 {
  1620  	if cacheItem, ok := channelMemberCountsCache.Get(channelId); ok {
  1621  		if s.metrics != nil {
  1622  			s.metrics.IncrementMemCacheHitCounter("Channel Member Counts")
  1623  		}
  1624  		return cacheItem.(int64)
  1625  	}
  1626  
  1627  	if s.metrics != nil {
  1628  		s.metrics.IncrementMemCacheMissCounter("Channel Member Counts")
  1629  	}
  1630  
  1631  	result := <-s.GetMemberCount(channelId, true)
  1632  	if result.Err != nil {
  1633  		return 0
  1634  	}
  1635  
  1636  	return result.Data.(int64)
  1637  }
  1638  
  1639  func (s SqlChannelStore) GetMemberCount(channelId string, allowFromCache bool) store.StoreChannel {
  1640  	return store.Do(func(result *store.StoreResult) {
  1641  		if allowFromCache {
  1642  			if cacheItem, ok := channelMemberCountsCache.Get(channelId); ok {
  1643  				if s.metrics != nil {
  1644  					s.metrics.IncrementMemCacheHitCounter("Channel Member Counts")
  1645  				}
  1646  				result.Data = cacheItem.(int64)
  1647  				return
  1648  			}
  1649  		}
  1650  
  1651  		if s.metrics != nil {
  1652  			s.metrics.IncrementMemCacheMissCounter("Channel Member Counts")
  1653  		}
  1654  
  1655  		count, err := s.GetReplica().SelectInt(`
  1656  			SELECT
  1657  				count(*)
  1658  			FROM
  1659  				ChannelMembers,
  1660  				Users
  1661  			WHERE
  1662  				ChannelMembers.UserId = Users.Id
  1663  				AND ChannelMembers.ChannelId = :ChannelId
  1664  				AND Users.DeleteAt = 0`, map[string]interface{}{"ChannelId": channelId})
  1665  		if err != nil {
  1666  			result.Err = model.NewAppError("SqlChannelStore.GetMemberCount", "store.sql_channel.get_member_count.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
  1667  			return
  1668  		}
  1669  		result.Data = count
  1670  
  1671  		if allowFromCache {
  1672  			channelMemberCountsCache.AddWithExpiresInSecs(channelId, count, CHANNEL_MEMBERS_COUNTS_CACHE_SEC)
  1673  		}
  1674  	})
  1675  }
  1676  
  1677  func (s SqlChannelStore) RemoveMember(channelId string, userId string) store.StoreChannel {
  1678  	return store.Do(func(result *store.StoreResult) {
  1679  		_, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId AND UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId})
  1680  		if err != nil {
  1681  			result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
  1682  		}
  1683  	})
  1684  }
  1685  
  1686  func (s SqlChannelStore) RemoveAllDeactivatedMembers(channelId string) store.StoreChannel {
  1687  	return store.Do(func(result *store.StoreResult) {
  1688  		query := `
  1689  			DELETE
  1690  			FROM
  1691  				ChannelMembers
  1692  			WHERE
  1693  				UserId IN (
  1694  					SELECT
  1695  						Id
  1696  					FROM
  1697  						Users
  1698  					WHERE
  1699  						Users.DeleteAt != 0
  1700  				)
  1701  			AND
  1702  				ChannelMembers.ChannelId = :ChannelId
  1703  		`
  1704  
  1705  		_, err := s.GetMaster().Exec(query, map[string]interface{}{"ChannelId": channelId})
  1706  		if err != nil {
  1707  			result.Err = model.NewAppError("SqlChannelStore.RemoveAllDeactivatedMembers", "store.sql_channel.remove_all_deactivated_members.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
  1708  		}
  1709  	})
  1710  }
  1711  
  1712  func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) store.StoreChannel {
  1713  	return store.Do(func(result *store.StoreResult) {
  1714  		if _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
  1715  			result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.permanent_delete_members_by_user.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
  1716  		}
  1717  	})
  1718  }
  1719  
  1720  func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string) store.StoreChannel {
  1721  	return store.Do(func(result *store.StoreResult) {
  1722  		props := make(map[string]interface{})
  1723  
  1724  		updateIdQuery := ""
  1725  		for index, channelId := range channelIds {
  1726  			if len(updateIdQuery) > 0 {
  1727  				updateIdQuery += " OR "
  1728  			}
  1729  
  1730  			props["channelId"+strconv.Itoa(index)] = channelId
  1731  			updateIdQuery += "ChannelId = :channelId" + strconv.Itoa(index)
  1732  		}
  1733  
  1734  		selectIdQuery := strings.Replace(updateIdQuery, "ChannelId", "Id", -1)
  1735  
  1736  		var lastPostAtTimes []struct {
  1737  			Id            string
  1738  			LastPostAt    int64
  1739  			TotalMsgCount int64
  1740  		}
  1741  
  1742  		selectQuery := "SELECT Id, LastPostAt, TotalMsgCount FROM Channels WHERE (" + selectIdQuery + ")"
  1743  
  1744  		if _, err := s.GetMaster().Select(&lastPostAtTimes, selectQuery, props); err != nil || len(lastPostAtTimes) <= 0 {
  1745  			var extra string
  1746  			status := http.StatusInternalServerError
  1747  			if err == nil {
  1748  				status = http.StatusBadRequest
  1749  				extra = "No channels found"
  1750  			} else {
  1751  				extra = err.Error()
  1752  			}
  1753  			result.Err = model.NewAppError("SqlChannelStore.UpdateLastViewedAt", "store.sql_channel.update_last_viewed_at.app_error", nil, "channel_ids="+strings.Join(channelIds, ",")+", user_id="+userId+", "+extra, status)
  1754  			return
  1755  		}
  1756  
  1757  		times := map[string]int64{}
  1758  		msgCountQuery := ""
  1759  		lastViewedQuery := ""
  1760  		for index, t := range lastPostAtTimes {
  1761  			times[t.Id] = t.LastPostAt
  1762  
  1763  			props["msgCount"+strconv.Itoa(index)] = t.TotalMsgCount
  1764  			msgCountQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCount, :msgCount%d) ", index, index)
  1765  
  1766  			props["lastViewed"+strconv.Itoa(index)] = t.LastPostAt
  1767  			lastViewedQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(LastViewedAt, :lastViewed%d) ", index, index)
  1768  
  1769  			props["channelId"+strconv.Itoa(index)] = t.Id
  1770  		}
  1771  
  1772  		var updateQuery string
  1773  
  1774  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  1775  			updateQuery = `UPDATE
  1776  				ChannelMembers
  1777  			SET
  1778  			    MentionCount = 0,
  1779  			    MsgCount = CAST(CASE ChannelId ` + msgCountQuery + ` END AS BIGINT),
  1780  			    LastViewedAt = CAST(CASE ChannelId ` + lastViewedQuery + ` END AS BIGINT),
  1781  			    LastUpdateAt = CAST(CASE ChannelId ` + lastViewedQuery + ` END AS BIGINT)
  1782  			WHERE
  1783  			        UserId = :UserId
  1784  			        AND (` + updateIdQuery + `)`
  1785  		} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1786  			updateQuery = `UPDATE
  1787  				ChannelMembers
  1788  			SET
  1789  			    MentionCount = 0,
  1790  			    MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
  1791  			    LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
  1792  			    LastUpdateAt = CASE ChannelId ` + lastViewedQuery + ` END
  1793  			WHERE
  1794  			        UserId = :UserId
  1795  			        AND (` + updateIdQuery + `)`
  1796  		}
  1797  
  1798  		props["UserId"] = userId
  1799  
  1800  		if _, err := s.GetMaster().Exec(updateQuery, props); err != nil {
  1801  			result.Err = model.NewAppError("SqlChannelStore.UpdateLastViewedAt", "store.sql_channel.update_last_viewed_at.app_error", nil, "channel_ids="+strings.Join(channelIds, ",")+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
  1802  			return
  1803  		}
  1804  
  1805  		result.Data = times
  1806  	})
  1807  }
  1808  
  1809  func (s SqlChannelStore) IncrementMentionCount(channelId string, userId string) store.StoreChannel {
  1810  	return store.Do(func(result *store.StoreResult) {
  1811  		_, err := s.GetMaster().Exec(
  1812  			`UPDATE
  1813  				ChannelMembers
  1814  			SET
  1815  				MentionCount = MentionCount + 1,
  1816  				LastUpdateAt = :LastUpdateAt
  1817  			WHERE
  1818  				UserId = :UserId
  1819  					AND ChannelId = :ChannelId`,
  1820  			map[string]interface{}{"ChannelId": channelId, "UserId": userId, "LastUpdateAt": model.GetMillis()})
  1821  		if err != nil {
  1822  			result.Err = model.NewAppError("SqlChannelStore.IncrementMentionCount", "store.sql_channel.increment_mention_count.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
  1823  		}
  1824  	})
  1825  }
  1826  
  1827  func (s SqlChannelStore) GetAll(teamId string) store.StoreChannel {
  1828  	return store.Do(func(result *store.StoreResult) {
  1829  		var data []*model.Channel
  1830  		_, err := s.GetReplica().Select(&data, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Type != 'D' ORDER BY Name", map[string]interface{}{"TeamId": teamId})
  1831  
  1832  		if err != nil {
  1833  			result.Err = model.NewAppError("SqlChannelStore.GetAll", "store.sql_channel.get_all.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError)
  1834  			return
  1835  		}
  1836  
  1837  		result.Data = data
  1838  	})
  1839  }
  1840  
  1841  func (s SqlChannelStore) GetChannelsByIds(channelIds []string) store.StoreChannel {
  1842  	return store.Do(func(result *store.StoreResult) {
  1843  		keys, params := MapStringsToQueryParams(channelIds, "Channel")
  1844  
  1845  		query := `SELECT * FROM Channels WHERE Id IN ` + keys + ` ORDER BY Name`
  1846  
  1847  		var channels []*model.Channel
  1848  		_, err := s.GetReplica().Select(&channels, query, params)
  1849  
  1850  		if err != nil {
  1851  			mlog.Error(fmt.Sprint(err))
  1852  			result.Err = model.NewAppError("SqlChannelStore.GetChannelsByIds", "store.sql_channel.get_channels_by_ids.app_error", nil, "", http.StatusInternalServerError)
  1853  		} else {
  1854  			result.Data = channels
  1855  		}
  1856  	})
  1857  }
  1858  
  1859  func (s SqlChannelStore) GetForPost(postId string) store.StoreChannel {
  1860  	return store.Do(func(result *store.StoreResult) {
  1861  		channel := &model.Channel{}
  1862  		if err := s.GetReplica().SelectOne(
  1863  			channel,
  1864  			`SELECT
  1865  				Channels.*
  1866  			FROM
  1867  				Channels,
  1868  				Posts
  1869  			WHERE
  1870  				Channels.Id = Posts.ChannelId
  1871  				AND Posts.Id = :PostId`, map[string]interface{}{"PostId": postId}); err != nil {
  1872  			result.Err = model.NewAppError("SqlChannelStore.GetForPost", "store.sql_channel.get_for_post.app_error", nil, "postId="+postId+", err="+err.Error(), http.StatusInternalServerError)
  1873  			return
  1874  		}
  1875  
  1876  		result.Data = channel
  1877  	})
  1878  }
  1879  
  1880  func (s SqlChannelStore) AnalyticsTypeCount(teamId string, channelType string) store.StoreChannel {
  1881  	return store.Do(func(result *store.StoreResult) {
  1882  		query := "SELECT COUNT(Id) AS Value FROM Channels WHERE Type = :ChannelType"
  1883  
  1884  		if len(teamId) > 0 {
  1885  			query += " AND TeamId = :TeamId"
  1886  		}
  1887  
  1888  		v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId, "ChannelType": channelType})
  1889  		if err != nil {
  1890  			result.Err = model.NewAppError("SqlChannelStore.AnalyticsTypeCount", "store.sql_channel.analytics_type_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1891  			return
  1892  		}
  1893  
  1894  		result.Data = v
  1895  	})
  1896  }
  1897  
  1898  func (s SqlChannelStore) AnalyticsDeletedTypeCount(teamId string, channelType string) store.StoreChannel {
  1899  	return store.Do(func(result *store.StoreResult) {
  1900  		query := "SELECT COUNT(Id) AS Value FROM Channels WHERE Type = :ChannelType AND DeleteAt > 0"
  1901  
  1902  		if len(teamId) > 0 {
  1903  			query += " AND TeamId = :TeamId"
  1904  		}
  1905  
  1906  		v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId, "ChannelType": channelType})
  1907  		if err != nil {
  1908  			result.Err = model.NewAppError("SqlChannelStore.AnalyticsDeletedTypeCount", "store.sql_channel.analytics_deleted_type_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1909  			return
  1910  		}
  1911  
  1912  		result.Data = v
  1913  	})
  1914  }
  1915  
  1916  func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) store.StoreChannel {
  1917  	return store.Do(func(result *store.StoreResult) {
  1918  		var dbMembers channelMemberWithSchemeRolesList
  1919  		_, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId})
  1920  
  1921  		if err != nil {
  1922  			result.Err = model.NewAppError("SqlChannelStore.GetMembersForUser", "store.sql_channel.get_members.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  1923  			return
  1924  		}
  1925  
  1926  		result.Data = dbMembers.ToModel()
  1927  	})
  1928  }
  1929  
  1930  func (s SqlChannelStore) GetMembersForUserWithPagination(teamId, userId string, page, perPage int) store.StoreChannel {
  1931  	return store.Do(func(result *store.StoreResult) {
  1932  		var dbMembers channelMemberWithSchemeRolesList
  1933  		offset := page * perPage
  1934  		_, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.UserId = :UserId Limit :Limit Offset :Offset", map[string]interface{}{"TeamId": teamId, "UserId": userId, "Limit": perPage, "Offset": offset})
  1935  
  1936  		if err != nil {
  1937  			result.Err = model.NewAppError("SqlChannelStore.GetMembersForUserWithPagination", "store.sql_channel.get_members.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  1938  			return
  1939  		}
  1940  
  1941  		result.Data = dbMembers.ToModel()
  1942  	})
  1943  }
  1944  
  1945  func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel {
  1946  	return store.Do(func(result *store.StoreResult) {
  1947  		deleteFilter := "AND c.DeleteAt = 0"
  1948  		if includeDeleted {
  1949  			deleteFilter = ""
  1950  		}
  1951  
  1952  		queryFormat := `
  1953  			SELECT
  1954  			    Channels.*
  1955  			FROM
  1956  			    Channels
  1957  			JOIN
  1958  			    PublicChannels c ON (c.Id = Channels.Id)
  1959  			WHERE
  1960  			    c.TeamId = :TeamId
  1961  			    ` + deleteFilter + `
  1962  			    %v
  1963  			LIMIT ` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT)
  1964  
  1965  		var channels model.ChannelList
  1966  
  1967  		if likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose"); likeClause == "" {
  1968  			if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil {
  1969  				result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  1970  			}
  1971  		} else {
  1972  			// Using a UNION results in index_merge and fulltext queries and is much faster than the ref
  1973  			// query you would get using an OR of the LIKE and full-text clauses.
  1974  			fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  1975  			likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
  1976  			fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
  1977  			query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
  1978  
  1979  			if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil {
  1980  				result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  1981  			}
  1982  		}
  1983  
  1984  		sort.Slice(channels, func(a, b int) bool {
  1985  			return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName)
  1986  		})
  1987  		result.Data = &channels
  1988  	})
  1989  }
  1990  
  1991  func (s SqlChannelStore) AutocompleteInTeamForSearch(teamId string, userId string, term string, includeDeleted bool) store.StoreChannel {
  1992  	return store.Do(func(result *store.StoreResult) {
  1993  		deleteFilter := "AND DeleteAt = 0"
  1994  		if includeDeleted {
  1995  			deleteFilter = ""
  1996  		}
  1997  
  1998  		queryFormat := `
  1999  			SELECT
  2000  				C.*
  2001  			FROM
  2002  				Channels AS C
  2003  			JOIN
  2004  				ChannelMembers AS CM ON CM.ChannelId = C.Id
  2005  			WHERE
  2006  			    (C.TeamId = :TeamId OR (C.TeamId = '' AND C.Type = 'G'))
  2007  				AND CM.UserId = :UserId
  2008  				` + deleteFilter + `
  2009  				%v
  2010  			LIMIT 50`
  2011  
  2012  		var channels model.ChannelList
  2013  
  2014  		if likeClause, likeTerm := s.buildLIKEClause(term, "Name, DisplayName, Purpose"); likeClause == "" {
  2015  			if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId, "UserId": userId}); err != nil {
  2016  				result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeamForSearch", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2017  			}
  2018  		} else {
  2019  			// Using a UNION results in index_merge and fulltext queries and is much faster than the ref
  2020  			// query you would get using an OR of the LIKE and full-text clauses.
  2021  			fulltextClause, fulltextTerm := s.buildFulltextClause(term, "Name, DisplayName, Purpose")
  2022  			likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
  2023  			fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
  2024  			query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
  2025  
  2026  			if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "UserId": userId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil {
  2027  				result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeamForSearch", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2028  			}
  2029  		}
  2030  
  2031  		directChannels, err := s.autocompleteInTeamForSearchDirectMessages(userId, term)
  2032  		if err != nil {
  2033  			result.Err = err
  2034  			return
  2035  		}
  2036  
  2037  		channels = append(channels, directChannels...)
  2038  
  2039  		sort.Slice(channels, func(a, b int) bool {
  2040  			return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName)
  2041  		})
  2042  		result.Data = &channels
  2043  	})
  2044  }
  2045  
  2046  func (s SqlChannelStore) autocompleteInTeamForSearchDirectMessages(userId string, term string) ([]*model.Channel, *model.AppError) {
  2047  	queryFormat := `
  2048  			SELECT
  2049  				C.*,
  2050  				OtherUsers.Username as DisplayName
  2051  			FROM
  2052  				Channels AS C
  2053  			JOIN
  2054  				ChannelMembers AS CM ON CM.ChannelId = C.Id
  2055  			INNER JOIN (
  2056  				SELECT
  2057  					ICM.ChannelId AS ChannelId, IU.Username AS Username
  2058  				FROM
  2059  					Users as IU
  2060  				JOIN
  2061  					ChannelMembers AS ICM ON ICM.UserId = IU.Id
  2062  				WHERE
  2063  					IU.Id != :UserId
  2064  					%v
  2065  				) AS OtherUsers ON OtherUsers.ChannelId = C.Id
  2066  			WHERE
  2067  			    C.Type = 'D'
  2068  				AND CM.UserId = :UserId
  2069  			LIMIT 50`
  2070  
  2071  	var channels model.ChannelList
  2072  
  2073  	if likeClause, likeTerm := s.buildLIKEClause(term, "IU.Username, IU.Nickname"); likeClause == "" {
  2074  		if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"UserId": userId}); err != nil {
  2075  			return nil, model.NewAppError("SqlChannelStore.AutocompleteInTeamForSearch", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2076  		}
  2077  	} else {
  2078  		query := fmt.Sprintf(queryFormat, "AND "+likeClause)
  2079  
  2080  		if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"UserId": userId, "LikeTerm": likeTerm}); err != nil {
  2081  			return nil, model.NewAppError("SqlChannelStore.AutocompleteInTeamForSearch", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2082  		}
  2083  	}
  2084  
  2085  	return channels, nil
  2086  }
  2087  
  2088  func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel {
  2089  	return store.Do(func(result *store.StoreResult) {
  2090  		deleteFilter := "AND c.DeleteAt = 0"
  2091  		if includeDeleted {
  2092  			deleteFilter = ""
  2093  		}
  2094  
  2095  		*result = s.performSearch(`
  2096  			SELECT
  2097  			    Channels.*
  2098  			FROM
  2099  			    Channels
  2100  			JOIN
  2101  			    PublicChannels c ON (c.Id = Channels.Id)
  2102  			WHERE
  2103  			    c.TeamId = :TeamId
  2104  			    `+deleteFilter+`
  2105  			    SEARCH_CLAUSE
  2106  			ORDER BY c.DisplayName
  2107  			LIMIT 100
  2108  		`, term, map[string]interface{}{
  2109  			"TeamId": teamId,
  2110  		})
  2111  	})
  2112  }
  2113  
  2114  func (s SqlChannelStore) SearchAllChannels(term string, includeDeleted bool) store.StoreChannel {
  2115  	return store.Do(func(result *store.StoreResult) {
  2116  		parameters := map[string]interface{}{}
  2117  		deleteFilter := "AND c.DeleteAt = 0"
  2118  		if includeDeleted {
  2119  			deleteFilter = ""
  2120  		}
  2121  		searchQuery := `SELECT c.*, t.DisplayName AS TeamDisplayName, t.Name AS TeamName, t.UpdateAt as TeamUpdateAt FROM Channels AS c JOIN Teams AS t ON t.Id = c.TeamId WHERE (c.Type = 'P' OR c.Type = 'O') ` + deleteFilter + ` SEARCH_CLAUSE ORDER BY c.DisplayName, t.DisplayName LIMIT 100`
  2122  
  2123  		likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
  2124  		if likeTerm == "" {
  2125  			// If the likeTerm is empty after preparing, then don't bother searching.
  2126  			searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1)
  2127  		} else {
  2128  			parameters["LikeTerm"] = likeTerm
  2129  			fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  2130  			parameters["FulltextTerm"] = fulltextTerm
  2131  			searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1)
  2132  		}
  2133  
  2134  		var channels model.ChannelListWithTeamData
  2135  
  2136  		if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil {
  2137  			result.Err = model.NewAppError("SqlChannelStore.Search", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2138  		}
  2139  
  2140  		result.Data = &channels
  2141  	})
  2142  }
  2143  
  2144  func (s SqlChannelStore) SearchMore(userId string, teamId string, term string) store.StoreChannel {
  2145  	return store.Do(func(result *store.StoreResult) {
  2146  		*result = s.performSearch(`
  2147  			SELECT
  2148  			    Channels.*
  2149  			FROM
  2150  			    Channels
  2151  			JOIN
  2152  			    PublicChannels c ON (c.Id = Channels.Id)
  2153  			WHERE
  2154  			    c.TeamId = :TeamId
  2155  			AND c.DeleteAt = 0
  2156  			AND c.Id NOT IN (
  2157  			    SELECT
  2158  			        c.Id
  2159  			    FROM
  2160  			        PublicChannels c
  2161  			    JOIN
  2162  			        ChannelMembers cm ON (cm.ChannelId = c.Id)
  2163  			    WHERE
  2164  			        c.TeamId = :TeamId
  2165  			    AND cm.UserId = :UserId
  2166  			    AND c.DeleteAt = 0
  2167  		        )
  2168  			SEARCH_CLAUSE
  2169  			ORDER BY c.DisplayName
  2170  			LIMIT 100
  2171  		`, term, map[string]interface{}{
  2172  			"TeamId": teamId,
  2173  			"UserId": userId,
  2174  		})
  2175  	})
  2176  }
  2177  
  2178  func (s SqlChannelStore) buildLIKEClause(term string, searchColumns string) (likeClause, likeTerm string) {
  2179  	likeTerm = term
  2180  
  2181  	// These chars must be removed from the like query.
  2182  	for _, c := range ignoreLikeSearchChar {
  2183  		likeTerm = strings.Replace(likeTerm, c, "", -1)
  2184  	}
  2185  
  2186  	// These chars must be escaped in the like query.
  2187  	for _, c := range escapeLikeSearchChar {
  2188  		likeTerm = strings.Replace(likeTerm, c, "*"+c, -1)
  2189  	}
  2190  
  2191  	if likeTerm == "" {
  2192  		return
  2193  	}
  2194  
  2195  	// Prepare the LIKE portion of the query.
  2196  	var searchFields []string
  2197  	for _, field := range strings.Split(searchColumns, ", ") {
  2198  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2199  			searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*'", field, ":LikeTerm"))
  2200  		} else {
  2201  			searchFields = append(searchFields, fmt.Sprintf("%s LIKE %s escape '*'", field, ":LikeTerm"))
  2202  		}
  2203  	}
  2204  
  2205  	likeClause = fmt.Sprintf("(%s)", strings.Join(searchFields, " OR "))
  2206  	likeTerm += "%"
  2207  	return
  2208  }
  2209  
  2210  func (s SqlChannelStore) buildFulltextClause(term string, searchColumns string) (fulltextClause, fulltextTerm string) {
  2211  	// Copy the terms as we will need to prepare them differently for each search type.
  2212  	fulltextTerm = term
  2213  
  2214  	// These chars must be treated as spaces in the fulltext query.
  2215  	for _, c := range spaceFulltextSearchChar {
  2216  		fulltextTerm = strings.Replace(fulltextTerm, c, " ", -1)
  2217  	}
  2218  
  2219  	// Prepare the FULLTEXT portion of the query.
  2220  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2221  		fulltextTerm = strings.Replace(fulltextTerm, "|", "", -1)
  2222  
  2223  		splitTerm := strings.Fields(fulltextTerm)
  2224  		for i, t := range strings.Fields(fulltextTerm) {
  2225  			if i == len(splitTerm)-1 {
  2226  				splitTerm[i] = t + ":*"
  2227  			} else {
  2228  				splitTerm[i] = t + ":* &"
  2229  			}
  2230  		}
  2231  
  2232  		fulltextTerm = strings.Join(splitTerm, " ")
  2233  
  2234  		fulltextClause = fmt.Sprintf("((%s) @@ to_tsquery(:FulltextTerm))", convertMySQLFullTextColumnsToPostgres(searchColumns))
  2235  	} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  2236  		splitTerm := strings.Fields(fulltextTerm)
  2237  		for i, t := range strings.Fields(fulltextTerm) {
  2238  			splitTerm[i] = "+" + t + "*"
  2239  		}
  2240  
  2241  		fulltextTerm = strings.Join(splitTerm, " ")
  2242  
  2243  		fulltextClause = fmt.Sprintf("MATCH(%s) AGAINST (:FulltextTerm IN BOOLEAN MODE)", searchColumns)
  2244  	}
  2245  
  2246  	return
  2247  }
  2248  
  2249  func (s SqlChannelStore) performSearch(searchQuery string, term string, parameters map[string]interface{}) store.StoreResult {
  2250  	result := store.StoreResult{}
  2251  
  2252  	likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
  2253  	if likeTerm == "" {
  2254  		// If the likeTerm is empty after preparing, then don't bother searching.
  2255  		searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1)
  2256  	} else {
  2257  		parameters["LikeTerm"] = likeTerm
  2258  		fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  2259  		parameters["FulltextTerm"] = fulltextTerm
  2260  		searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1)
  2261  	}
  2262  
  2263  	var channels model.ChannelList
  2264  
  2265  	if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil {
  2266  		result.Err = model.NewAppError("SqlChannelStore.Search", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2267  		return result
  2268  	}
  2269  
  2270  	result.Data = &channels
  2271  	return result
  2272  }
  2273  
  2274  func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) store.StoreChannel {
  2275  	return store.Do(func(result *store.StoreResult) {
  2276  		var dbMembers channelMemberWithSchemeRolesList
  2277  		props := make(map[string]interface{})
  2278  		idQuery := ""
  2279  
  2280  		for index, userId := range userIds {
  2281  			if len(idQuery) > 0 {
  2282  				idQuery += ", "
  2283  			}
  2284  
  2285  			props["userId"+strconv.Itoa(index)] = userId
  2286  			idQuery += ":userId" + strconv.Itoa(index)
  2287  		}
  2288  
  2289  		props["ChannelId"] = channelId
  2290  
  2291  		if _, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId IN ("+idQuery+")", props); err != nil {
  2292  			result.Err = model.NewAppError("SqlChannelStore.GetMembersByIds", "store.sql_channel.get_members_by_ids.app_error", nil, "channelId="+channelId+" "+err.Error(), http.StatusInternalServerError)
  2293  			return
  2294  		}
  2295  
  2296  		result.Data = dbMembers.ToModel()
  2297  	})
  2298  }
  2299  
  2300  func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) store.StoreChannel {
  2301  	return store.Do(func(result *store.StoreResult) {
  2302  		var channels model.ChannelList
  2303  		_, err := s.GetReplica().Select(&channels, "SELECT * FROM Channels WHERE SchemeId = :SchemeId ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"SchemeId": schemeId, "Offset": offset, "Limit": limit})
  2304  		if err != nil {
  2305  			result.Err = model.NewAppError("SqlChannelStore.GetChannelsByScheme", "store.sql_channel.get_by_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError)
  2306  			return
  2307  		}
  2308  		result.Data = channels
  2309  	})
  2310  }
  2311  
  2312  // This function does the Advanced Permissions Phase 2 migration for ChannelMember objects. It performs the migration
  2313  // in batches as a single transaction per batch to ensure consistency but to also minimise execution time to avoid
  2314  // causing unnecessary table locks. **THIS FUNCTION SHOULD NOT BE USED FOR ANY OTHER PURPOSE.** Executing this function
  2315  // *after* the new Schemes functionality has been used on an installation will have unintended consequences.
  2316  func (s SqlChannelStore) MigrateChannelMembers(fromChannelId string, fromUserId string) store.StoreChannel {
  2317  	return store.Do(func(result *store.StoreResult) {
  2318  		var transaction *gorp.Transaction
  2319  		var err error
  2320  
  2321  		if transaction, err = s.GetMaster().Begin(); err != nil {
  2322  			result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2323  			return
  2324  		}
  2325  		defer finalizeTransaction(transaction)
  2326  
  2327  		var channelMembers []channelMember
  2328  		if _, err := transaction.Select(&channelMembers, "SELECT * from ChannelMembers WHERE (ChannelId, UserId) > (:FromChannelId, :FromUserId) ORDER BY ChannelId, UserId LIMIT 100", map[string]interface{}{"FromChannelId": fromChannelId, "FromUserId": fromUserId}); err != nil {
  2329  			result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.select.app_error", nil, err.Error(), http.StatusInternalServerError)
  2330  			return
  2331  		}
  2332  
  2333  		if len(channelMembers) == 0 {
  2334  			// No more channel members in query result means that the migration has finished.
  2335  			return
  2336  		}
  2337  
  2338  		for _, member := range channelMembers {
  2339  			roles := strings.Fields(member.Roles)
  2340  			var newRoles []string
  2341  			if !member.SchemeAdmin.Valid {
  2342  				member.SchemeAdmin = sql.NullBool{Bool: false, Valid: true}
  2343  			}
  2344  			if !member.SchemeUser.Valid {
  2345  				member.SchemeUser = sql.NullBool{Bool: false, Valid: true}
  2346  			}
  2347  			for _, role := range roles {
  2348  				if role == model.CHANNEL_ADMIN_ROLE_ID {
  2349  					member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true}
  2350  				} else if role == model.CHANNEL_USER_ROLE_ID {
  2351  					member.SchemeUser = sql.NullBool{Bool: true, Valid: true}
  2352  				} else {
  2353  					newRoles = append(newRoles, role)
  2354  				}
  2355  			}
  2356  			member.Roles = strings.Join(newRoles, " ")
  2357  
  2358  			if _, err := transaction.Update(&member); err != nil {
  2359  				result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.update.app_error", nil, err.Error(), http.StatusInternalServerError)
  2360  				return
  2361  			}
  2362  
  2363  		}
  2364  
  2365  		if err := transaction.Commit(); err != nil {
  2366  			result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2367  			return
  2368  		}
  2369  
  2370  		data := make(map[string]string)
  2371  		data["ChannelId"] = channelMembers[len(channelMembers)-1].ChannelId
  2372  		data["UserId"] = channelMembers[len(channelMembers)-1].UserId
  2373  		result.Data = data
  2374  	})
  2375  }
  2376  
  2377  func (s SqlChannelStore) ResetAllChannelSchemes() store.StoreChannel {
  2378  	return store.Do(func(result *store.StoreResult) {
  2379  		transaction, err := s.GetMaster().Begin()
  2380  		if err != nil {
  2381  			result.Err = model.NewAppError("SqlChannelStore.ResetAllChannelSchemes", "store.sql_channel.reset_all_channel_schemes.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2382  			return
  2383  		}
  2384  		defer finalizeTransaction(transaction)
  2385  
  2386  		*result = s.resetAllChannelSchemesT(transaction)
  2387  		if result.Err != nil {
  2388  			return
  2389  		}
  2390  
  2391  		if err := transaction.Commit(); err != nil {
  2392  			result.Err = model.NewAppError("SqlChannelStore.ResetAllChannelSchemes", "store.sql_channel.reset_all_channel_schemes.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2393  			return
  2394  		}
  2395  	})
  2396  }
  2397  
  2398  func (s SqlChannelStore) resetAllChannelSchemesT(transaction *gorp.Transaction) store.StoreResult {
  2399  	result := store.StoreResult{}
  2400  
  2401  	if _, err := transaction.Exec("UPDATE Channels SET SchemeId=''"); err != nil {
  2402  		result.Err = model.NewAppError("SqlChannelStore.ResetAllChannelSchemes", "store.sql_channel.reset_all_channel_schemes.app_error", nil, err.Error(), http.StatusInternalServerError)
  2403  		return result
  2404  	}
  2405  
  2406  	return result
  2407  }
  2408  
  2409  func (s SqlChannelStore) ClearAllCustomRoleAssignments() store.StoreChannel {
  2410  	return store.Do(func(result *store.StoreResult) {
  2411  		builtInRoles := model.MakeDefaultRoles()
  2412  		lastUserId := strings.Repeat("0", 26)
  2413  		lastChannelId := strings.Repeat("0", 26)
  2414  
  2415  		for {
  2416  			var transaction *gorp.Transaction
  2417  			var err error
  2418  
  2419  			if transaction, err = s.GetMaster().Begin(); err != nil {
  2420  				result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2421  				return
  2422  			}
  2423  
  2424  			var channelMembers []*channelMember
  2425  			if _, err := transaction.Select(&channelMembers, "SELECT * from ChannelMembers WHERE (ChannelId, UserId) > (:ChannelId, :UserId) ORDER BY ChannelId, UserId LIMIT 1000", map[string]interface{}{"ChannelId": lastChannelId, "UserId": lastUserId}); err != nil {
  2426  				finalizeTransaction(transaction)
  2427  				result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.select.app_error", nil, err.Error(), http.StatusInternalServerError)
  2428  				return
  2429  			}
  2430  
  2431  			if len(channelMembers) == 0 {
  2432  				finalizeTransaction(transaction)
  2433  				break
  2434  			}
  2435  
  2436  			for _, member := range channelMembers {
  2437  				lastUserId = member.UserId
  2438  				lastChannelId = member.ChannelId
  2439  
  2440  				var newRoles []string
  2441  
  2442  				for _, role := range strings.Fields(member.Roles) {
  2443  					for name := range builtInRoles {
  2444  						if name == role {
  2445  							newRoles = append(newRoles, role)
  2446  							break
  2447  						}
  2448  					}
  2449  				}
  2450  
  2451  				newRolesString := strings.Join(newRoles, " ")
  2452  				if newRolesString != member.Roles {
  2453  					if _, err := transaction.Exec("UPDATE ChannelMembers SET Roles = :Roles WHERE UserId = :UserId AND ChannelId = :ChannelId", map[string]interface{}{"Roles": newRolesString, "ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
  2454  						finalizeTransaction(transaction)
  2455  						result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.update.app_error", nil, err.Error(), http.StatusInternalServerError)
  2456  						return
  2457  					}
  2458  				}
  2459  			}
  2460  
  2461  			if err := transaction.Commit(); err != nil {
  2462  				finalizeTransaction(transaction)
  2463  				result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2464  				return
  2465  			}
  2466  		}
  2467  	})
  2468  }
  2469  
  2470  func (s SqlChannelStore) GetAllChannelsForExportAfter(limit int, afterId string) store.StoreChannel {
  2471  	return store.Do(func(result *store.StoreResult) {
  2472  		var data []*model.ChannelForExport
  2473  		if _, err := s.GetReplica().Select(&data, `
  2474  			SELECT
  2475  				Channels.*,
  2476  				Teams.Name as TeamName,
  2477  				Schemes.Name as SchemeName
  2478  			FROM Channels
  2479  			INNER JOIN
  2480  				Teams ON Channels.TeamId = Teams.Id
  2481  			LEFT JOIN
  2482  				Schemes ON Channels.SchemeId = Schemes.Id
  2483  			WHERE
  2484  				Channels.Id > :AfterId
  2485  				AND Channels.Type IN ('O', 'P')
  2486  			ORDER BY
  2487  				Id
  2488  			LIMIT :Limit`,
  2489  			map[string]interface{}{"AfterId": afterId, "Limit": limit}); err != nil {
  2490  			result.Err = model.NewAppError("SqlTeamStore.GetAllChannelsForExportAfter", "store.sql_channel.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
  2491  			return
  2492  		}
  2493  
  2494  		result.Data = data
  2495  	})
  2496  }
  2497  
  2498  func (s SqlChannelStore) GetChannelMembersForExport(userId string, teamId string) store.StoreChannel {
  2499  	return store.Do(func(result *store.StoreResult) {
  2500  		var members []*model.ChannelMemberForExport
  2501  		_, err := s.GetReplica().Select(&members, `
  2502              SELECT
  2503                  ChannelMembers.*,
  2504                  Channels.Name as ChannelName
  2505              FROM
  2506                  ChannelMembers
  2507              INNER JOIN
  2508                  Channels ON ChannelMembers.ChannelId = Channels.Id
  2509              WHERE
  2510                  ChannelMembers.UserId = :UserId
  2511  				AND Channels.TeamId = :TeamId
  2512  				AND Channels.DeleteAt = 0`,
  2513  			map[string]interface{}{"TeamId": teamId, "UserId": userId})
  2514  
  2515  		if err != nil {
  2516  			result.Err = model.NewAppError("SqlChannelStore.GetChannelMembersForExport", "store.sql_channel.get_members.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  2517  			return
  2518  		}
  2519  
  2520  		result.Data = members
  2521  	})
  2522  }
  2523  
  2524  func (s SqlChannelStore) GetAllDirectChannelsForExportAfter(limit int, afterId string) store.StoreChannel {
  2525  	return store.Do(func(result *store.StoreResult) {
  2526  		var directChannelsForExport []*model.DirectChannelForExport
  2527  		query := s.getQueryBuilder().
  2528  			Select("Channels.*").
  2529  			From("Channels").
  2530  			Where(sq.And{
  2531  				sq.Gt{"Channels.Id": afterId},
  2532  				sq.Eq{"Channels.DeleteAt": int(0)},
  2533  				sq.Eq{"Channels.Type": []string{"D", "G"}},
  2534  			}).
  2535  			OrderBy("Channels.Id").
  2536  			Limit(uint64(limit))
  2537  
  2538  		queryString, args, err := query.ToSql()
  2539  		if err != nil {
  2540  			result.Err = model.NewAppError("SqlTeamStore.GetAllDirectChannelsForExportAfter", "store.sql_channel.get_all_direct.app_error", nil, err.Error(), http.StatusInternalServerError)
  2541  			return
  2542  		}
  2543  
  2544  		if _, err = s.GetReplica().Select(&directChannelsForExport, queryString, args...); err != nil {
  2545  			result.Err = model.NewAppError("SqlTeamStore.GetAllDirectChannelsForExportAfter", "store.sql_channel.get_all_direct.app_error", nil, err.Error(), http.StatusInternalServerError)
  2546  			return
  2547  		}
  2548  
  2549  		var channelIds []string
  2550  		for _, channel := range directChannelsForExport {
  2551  			channelIds = append(channelIds, channel.Id)
  2552  		}
  2553  		query = s.getQueryBuilder().
  2554  			Select("*").
  2555  			From("ChannelMembers cm").
  2556  			Join("Users u ON ( u.Id = cm.UserId )").
  2557  			Where(sq.And{
  2558  				sq.Eq{"cm.ChannelId": channelIds},
  2559  				sq.Eq{"u.DeleteAt": int(0)},
  2560  			})
  2561  
  2562  		queryString, args, err = query.ToSql()
  2563  		if err != nil {
  2564  			result.Err = model.NewAppError("SqlTeamStore.GetAllDirectChannelsForExportAfter", "store.sql_channel.get_all_direct.app_error", nil, err.Error(), http.StatusInternalServerError)
  2565  			return
  2566  		}
  2567  
  2568  		var channelMembers []*model.ChannelMemberForExport
  2569  		if _, err := s.GetReplica().Select(&channelMembers, queryString, args...); err != nil {
  2570  			result.Err = model.NewAppError("SqlTeamStore.GetAllDirectChannelsForExportAfter", "store.sql_channel.get_all_direct.app_error", nil, err.Error(), http.StatusInternalServerError)
  2571  		}
  2572  
  2573  		// Populate each channel with its members
  2574  		dmChannelsMap := make(map[string]*model.DirectChannelForExport)
  2575  		for _, channel := range directChannelsForExport {
  2576  			channel.Members = &[]string{}
  2577  			dmChannelsMap[channel.Id] = channel
  2578  		}
  2579  		for _, member := range channelMembers {
  2580  			members := dmChannelsMap[member.ChannelId].Members
  2581  			*members = append(*members, member.Username)
  2582  		}
  2583  		result.Data = directChannelsForExport
  2584  	})
  2585  }
  2586  
  2587  func (s SqlChannelStore) GetChannelsBatchForIndexing(startTime, endTime int64, limit int) store.StoreChannel {
  2588  	return store.Do(func(result *store.StoreResult) {
  2589  		var channels []*model.Channel
  2590  		_, err1 := s.GetSearchReplica().Select(&channels,
  2591  			`SELECT
  2592                   *
  2593               FROM
  2594                   Channels
  2595               WHERE
  2596                   Type = 'O'
  2597               AND
  2598                   CreateAt >= :StartTime
  2599               AND
  2600                   CreateAt < :EndTime
  2601               ORDER BY
  2602                   CreateAt
  2603               LIMIT
  2604                   :NumChannels`,
  2605  			map[string]interface{}{"StartTime": startTime, "EndTime": endTime, "NumChannels": limit})
  2606  
  2607  		if err1 != nil {
  2608  			result.Err = model.NewAppError("SqlChannelStore.GetChannelsBatchForIndexing", "store.sql_channel.get_channels_batch_for_indexing.get.app_error", nil, err1.Error(), http.StatusInternalServerError)
  2609  			return
  2610  		}
  2611  
  2612  		result.Data = channels
  2613  	})
  2614  }