github.com/mattermost/mattermost-server/v5@v5.39.3/store/sqlstore/upgrade.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  	"encoding/json"
     9  	"os"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/blang/semver"
    14  	"github.com/pkg/errors"
    15  
    16  	"github.com/mattermost/mattermost-server/v5/model"
    17  	"github.com/mattermost/mattermost-server/v5/services/timezones"
    18  	"github.com/mattermost/mattermost-server/v5/shared/mlog"
    19  )
    20  
    21  const (
    22  	CurrentSchemaVersion   = Version5390
    23  	Version5390            = "5.39.0"
    24  	Version5380            = "5.38.0"
    25  	Version5370            = "5.37.0"
    26  	Version5360            = "5.36.0"
    27  	Version5350            = "5.35.0"
    28  	Version5340            = "5.34.0"
    29  	Version5330            = "5.33.0"
    30  	Version5320            = "5.32.0"
    31  	Version5310            = "5.31.0"
    32  	Version5300            = "5.30.0"
    33  	Version5291            = "5.29.1"
    34  	Version5290            = "5.29.0"
    35  	Version5281            = "5.28.1"
    36  	Version5280            = "5.28.0"
    37  	Version5270            = "5.27.0"
    38  	Version5260            = "5.26.0"
    39  	Version5250            = "5.25.0"
    40  	Version5240            = "5.24.0"
    41  	Version5230            = "5.23.0"
    42  	Version5220            = "5.22.0"
    43  	Version5210            = "5.21.0"
    44  	Version5200            = "5.20.0"
    45  	Version5190            = "5.19.0"
    46  	Version5180            = "5.18.0"
    47  	Version5170            = "5.17.0"
    48  	Version5160            = "5.16.0"
    49  	Version5150            = "5.15.0"
    50  	Version5140            = "5.14.0"
    51  	Version5130            = "5.13.0"
    52  	Version5120            = "5.12.0"
    53  	Version5110            = "5.11.0"
    54  	Version5100            = "5.10.0"
    55  	Version590             = "5.9.0"
    56  	Version580             = "5.8.0"
    57  	Version570             = "5.7.0"
    58  	Version560             = "5.6.0"
    59  	Version550             = "5.5.0"
    60  	Version540             = "5.4.0"
    61  	Version530             = "5.3.0"
    62  	Version520             = "5.2.0"
    63  	Version510             = "5.1.0"
    64  	Version500             = "5.0.0"
    65  	Version4100            = "4.10.0"
    66  	Version490             = "4.9.0"
    67  	Version481             = "4.8.1"
    68  	Version480             = "4.8.0"
    69  	Version472             = "4.7.2"
    70  	Version471             = "4.7.1"
    71  	Version470             = "4.7.0"
    72  	Version460             = "4.6.0"
    73  	Version450             = "4.5.0"
    74  	Version440             = "4.4.0"
    75  	Version430             = "4.3.0"
    76  	Version420             = "4.2.0"
    77  	Version410             = "4.1.0"
    78  	Version400             = "4.0.0"
    79  	Version3100            = "3.10.0"
    80  	Version390             = "3.9.0"
    81  	Version380             = "3.8.0"
    82  	Version370             = "3.7.0"
    83  	Version360             = "3.6.0"
    84  	Version350             = "3.5.0"
    85  	Version340             = "3.4.0"
    86  	Version330             = "3.3.0"
    87  	Version320             = "3.2.0"
    88  	Version310             = "3.1.0"
    89  	Version300             = "3.0.0"
    90  	OldestSupportedVersion = Version300
    91  )
    92  
    93  const (
    94  	ExitVersionSave                 = 1003
    95  	ExitThemeMigration              = 1004
    96  	ExitTeamInviteIDMigrationFailed = 1006
    97  )
    98  
    99  // upgradeDatabase attempts to migrate the schema to the latest supported version.
   100  // The value of model.CurrentVersion is accepted as a parameter for unit testing, but it is not
   101  // used to stop migrations at that version.
   102  func upgradeDatabase(sqlStore *SqlStore, currentModelVersionString string) error {
   103  	currentModelVersion, err := semver.Parse(currentModelVersionString)
   104  	if err != nil {
   105  		return errors.Wrapf(err, "failed to parse current model version %s", currentModelVersionString)
   106  	}
   107  
   108  	nextUnsupportedMajorVersion := semver.Version{
   109  		Major: currentModelVersion.Major + 1,
   110  	}
   111  
   112  	oldestSupportedVersion, err := semver.Parse(OldestSupportedVersion)
   113  	if err != nil {
   114  		return errors.Wrapf(err, "failed to parse oldest supported version %s", OldestSupportedVersion)
   115  	}
   116  
   117  	var currentSchemaVersion *semver.Version
   118  	currentSchemaVersionString := sqlStore.GetCurrentSchemaVersion()
   119  	if currentSchemaVersionString != "" {
   120  		currentSchemaVersion, err = semver.New(currentSchemaVersionString)
   121  		if err != nil {
   122  			return errors.Wrapf(err, "failed to parse database schema version %s", currentSchemaVersionString)
   123  		}
   124  	}
   125  
   126  	// Assume a fresh database if no schema version has been recorded.
   127  	if currentSchemaVersion == nil {
   128  		if err := sqlStore.System().SaveOrUpdate(&model.System{Name: "Version", Value: currentModelVersion.String()}); err != nil {
   129  			return errors.Wrap(err, "failed to initialize schema version for fresh database")
   130  		}
   131  
   132  		currentSchemaVersion = &currentModelVersion
   133  		mlog.Info("The database schema version has been set", mlog.String("version", currentSchemaVersion.String()))
   134  		return nil
   135  	}
   136  
   137  	// Upgrades prior to the oldest supported version are not supported.
   138  	if currentSchemaVersion.LT(oldestSupportedVersion) {
   139  		return errors.Errorf("Database schema version %s is no longer supported. This Mattermost server supports automatic upgrades from schema version %s through schema version %s. Please manually upgrade to at least version %s before continuing.", *currentSchemaVersion, oldestSupportedVersion, currentModelVersion, oldestSupportedVersion)
   140  	}
   141  
   142  	// Allow forwards compatibility only within the same major version.
   143  	if currentSchemaVersion.GTE(nextUnsupportedMajorVersion) {
   144  		return errors.Errorf("Database schema version %s is not supported. This Mattermost server supports only >=%s, <%s. Please upgrade to at least version %s before continuing.", *currentSchemaVersion, currentModelVersion, nextUnsupportedMajorVersion, nextUnsupportedMajorVersion)
   145  	} else if currentSchemaVersion.GT(currentModelVersion) {
   146  		mlog.Warn("The database schema version and model versions do not match", mlog.String("schema_version", currentSchemaVersion.String()), mlog.String("model_version", currentModelVersion.String()))
   147  	}
   148  
   149  	// Otherwise, apply any necessary migrations. Note that these methods currently invoke
   150  	// os.Exit instead of returning an error.
   151  	upgradeDatabaseToVersion31(sqlStore)
   152  	upgradeDatabaseToVersion32(sqlStore)
   153  	upgradeDatabaseToVersion33(sqlStore)
   154  	upgradeDatabaseToVersion34(sqlStore)
   155  	upgradeDatabaseToVersion35(sqlStore)
   156  	upgradeDatabaseToVersion36(sqlStore)
   157  	upgradeDatabaseToVersion37(sqlStore)
   158  	upgradeDatabaseToVersion38(sqlStore)
   159  	upgradeDatabaseToVersion39(sqlStore)
   160  	upgradeDatabaseToVersion310(sqlStore)
   161  	upgradeDatabaseToVersion40(sqlStore)
   162  	upgradeDatabaseToVersion41(sqlStore)
   163  	upgradeDatabaseToVersion42(sqlStore)
   164  	upgradeDatabaseToVersion43(sqlStore)
   165  	upgradeDatabaseToVersion44(sqlStore)
   166  	upgradeDatabaseToVersion45(sqlStore)
   167  	upgradeDatabaseToVersion46(sqlStore)
   168  	upgradeDatabaseToVersion47(sqlStore)
   169  	upgradeDatabaseToVersion471(sqlStore)
   170  	upgradeDatabaseToVersion472(sqlStore)
   171  	upgradeDatabaseToVersion48(sqlStore)
   172  	upgradeDatabaseToVersion481(sqlStore)
   173  	upgradeDatabaseToVersion49(sqlStore)
   174  	upgradeDatabaseToVersion410(sqlStore)
   175  	upgradeDatabaseToVersion50(sqlStore)
   176  	upgradeDatabaseToVersion51(sqlStore)
   177  	upgradeDatabaseToVersion52(sqlStore)
   178  	upgradeDatabaseToVersion53(sqlStore)
   179  	upgradeDatabaseToVersion54(sqlStore)
   180  	upgradeDatabaseToVersion55(sqlStore)
   181  	upgradeDatabaseToVersion56(sqlStore)
   182  	upgradeDatabaseToVersion57(sqlStore)
   183  	upgradeDatabaseToVersion58(sqlStore)
   184  	upgradeDatabaseToVersion59(sqlStore)
   185  	upgradeDatabaseToVersion510(sqlStore)
   186  	upgradeDatabaseToVersion511(sqlStore)
   187  	upgradeDatabaseToVersion512(sqlStore)
   188  	upgradeDatabaseToVersion513(sqlStore)
   189  	upgradeDatabaseToVersion514(sqlStore)
   190  	upgradeDatabaseToVersion515(sqlStore)
   191  	upgradeDatabaseToVersion516(sqlStore)
   192  	upgradeDatabaseToVersion517(sqlStore)
   193  	upgradeDatabaseToVersion518(sqlStore)
   194  	upgradeDatabaseToVersion519(sqlStore)
   195  	upgradeDatabaseToVersion520(sqlStore)
   196  	upgradeDatabaseToVersion521(sqlStore)
   197  	upgradeDatabaseToVersion522(sqlStore)
   198  	upgradeDatabaseToVersion523(sqlStore)
   199  	upgradeDatabaseToVersion524(sqlStore)
   200  	upgradeDatabaseToVersion525(sqlStore)
   201  	upgradeDatabaseToVersion526(sqlStore)
   202  	upgradeDatabaseToVersion527(sqlStore)
   203  	upgradeDatabaseToVersion528(sqlStore)
   204  	upgradeDatabaseToVersion5281(sqlStore)
   205  	upgradeDatabaseToVersion529(sqlStore)
   206  	upgradeDatabaseToVersion5291(sqlStore)
   207  	upgradeDatabaseToVersion530(sqlStore)
   208  	upgradeDatabaseToVersion531(sqlStore)
   209  	upgradeDatabaseToVersion532(sqlStore)
   210  	upgradeDatabaseToVersion533(sqlStore)
   211  	upgradeDatabaseToVersion534(sqlStore)
   212  	upgradeDatabaseToVersion535(sqlStore)
   213  	upgradeDatabaseToVersion536(sqlStore)
   214  	upgradeDatabaseToVersion537(sqlStore)
   215  	upgradeDatabaseToVersion538(sqlStore)
   216  	upgradeDatabaseToVersion539(sqlStore)
   217  
   218  	return nil
   219  }
   220  
   221  func saveSchemaVersion(sqlStore *SqlStore, version string) {
   222  	if err := sqlStore.System().SaveOrUpdate(&model.System{Name: "Version", Value: version}); err != nil {
   223  		mlog.Critical(err.Error())
   224  		time.Sleep(time.Second)
   225  		os.Exit(ExitVersionSave)
   226  	}
   227  
   228  	mlog.Warn("The database schema version has been upgraded", mlog.String("version", version))
   229  }
   230  
   231  func shouldPerformUpgrade(sqlStore *SqlStore, currentSchemaVersion string, expectedSchemaVersion string) bool {
   232  	storedSchemaVersion := sqlStore.GetCurrentSchemaVersion()
   233  
   234  	storedVersion, err := semver.Parse(storedSchemaVersion)
   235  	if err != nil {
   236  		mlog.Error("Error parsing stored schema version", mlog.Err(err))
   237  		return false
   238  	}
   239  
   240  	currentVersion, err := semver.Parse(currentSchemaVersion)
   241  	if err != nil {
   242  		mlog.Error("Error parsing current schema version", mlog.Err(err))
   243  		return false
   244  	}
   245  
   246  	if storedVersion.Major == currentVersion.Major && storedVersion.Minor == currentVersion.Minor {
   247  		mlog.Warn("Attempting to upgrade the database schema version",
   248  			mlog.String("stored_version", storedSchemaVersion), mlog.String("current_version", currentSchemaVersion), mlog.String("new_version", expectedSchemaVersion))
   249  		return true
   250  	}
   251  
   252  	return false
   253  }
   254  
   255  func upgradeDatabaseToVersion31(sqlStore *SqlStore) {
   256  	if shouldPerformUpgrade(sqlStore, Version300, Version310) {
   257  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "")
   258  		saveSchemaVersion(sqlStore, Version310)
   259  	}
   260  }
   261  
   262  func upgradeDatabaseToVersion32(sqlStore *SqlStore) {
   263  	if shouldPerformUpgrade(sqlStore, Version310, Version320) {
   264  		saveSchemaVersion(sqlStore, Version320)
   265  	}
   266  }
   267  
   268  func themeMigrationFailed(err error) {
   269  	mlog.Critical("Failed to migrate User.ThemeProps to Preferences table", mlog.Err(err))
   270  	time.Sleep(time.Second)
   271  	os.Exit(ExitThemeMigration)
   272  }
   273  
   274  func upgradeDatabaseToVersion33(sqlStore *SqlStore) {
   275  	if shouldPerformUpgrade(sqlStore, Version320, Version330) {
   276  		if sqlStore.DoesColumnExist("Users", "ThemeProps") {
   277  			params := map[string]interface{}{
   278  				"Category": model.PREFERENCE_CATEGORY_THEME,
   279  				"Name":     "",
   280  			}
   281  
   282  			transaction, err := sqlStore.GetMaster().Begin()
   283  			if err != nil {
   284  				themeMigrationFailed(err)
   285  			}
   286  			defer finalizeTransaction(transaction)
   287  
   288  			// increase size of Value column of Preferences table to match the size of the ThemeProps column
   289  			if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   290  				if _, err := transaction.ExecNoTimeout("ALTER TABLE Preferences ALTER COLUMN Value TYPE varchar(2000)"); err != nil {
   291  					themeMigrationFailed(err)
   292  					return
   293  				}
   294  			} else if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
   295  				if _, err := transaction.ExecNoTimeout("ALTER TABLE Preferences MODIFY Value text"); err != nil {
   296  					themeMigrationFailed(err)
   297  					return
   298  				}
   299  			}
   300  
   301  			// copy data across
   302  			if _, err := transaction.ExecNoTimeout(
   303  				`INSERT INTO
   304  					Preferences(UserId, Category, Name, Value)
   305  				SELECT
   306  					Id, '`+model.PREFERENCE_CATEGORY_THEME+`', '', ThemeProps
   307  				FROM
   308  					Users
   309  				WHERE
   310  					Users.ThemeProps != 'null'`, params); err != nil {
   311  				themeMigrationFailed(err)
   312  				return
   313  			}
   314  
   315  			// delete old data
   316  			if _, err := transaction.ExecNoTimeout("ALTER TABLE Users DROP COLUMN ThemeProps"); err != nil {
   317  				themeMigrationFailed(err)
   318  				return
   319  			}
   320  
   321  			if err := transaction.Commit(); err != nil {
   322  				themeMigrationFailed(err)
   323  				return
   324  			}
   325  
   326  			// rename solarized_* code themes to solarized-* to match client changes in 3.0
   327  			var data model.Preferences
   328  			if _, err := sqlStore.GetMaster().Select(&data, "SELECT * FROM Preferences WHERE Category = '"+model.PREFERENCE_CATEGORY_THEME+"' AND Value LIKE '%solarized_%'"); err == nil {
   329  				for i := range data {
   330  					data[i].Value = strings.Replace(data[i].Value, "solarized_", "solarized-", -1)
   331  				}
   332  
   333  				sqlStore.Preference().Save(&data)
   334  			}
   335  		}
   336  
   337  		sqlStore.CreateColumnIfNotExists("OAuthApps", "IsTrusted", "tinyint(1)", "boolean", "0")
   338  		sqlStore.CreateColumnIfNotExists("OAuthApps", "IconURL", "varchar(512)", "varchar(512)", "")
   339  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ClientId", "varchar(26)", "varchar(26)", "")
   340  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "UserId", "varchar(26)", "varchar(26)", "")
   341  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ExpiresAt", "bigint", "bigint", "0")
   342  
   343  		if sqlStore.DoesColumnExist("OAuthAccessData", "AuthCode") {
   344  			sqlStore.RemoveIndexIfExists("idx_oauthaccessdata_auth_code", "OAuthAccessData")
   345  			sqlStore.RemoveColumnIfExists("OAuthAccessData", "AuthCode")
   346  		}
   347  
   348  		sqlStore.RemoveColumnIfExists("Users", "LastActivityAt")
   349  		sqlStore.RemoveColumnIfExists("Users", "LastPingAt")
   350  
   351  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "TriggerWhen", "tinyint", "integer", "0")
   352  
   353  		saveSchemaVersion(sqlStore, Version330)
   354  	}
   355  }
   356  
   357  func upgradeDatabaseToVersion34(sqlStore *SqlStore) {
   358  	if shouldPerformUpgrade(sqlStore, Version330, Version340) {
   359  		sqlStore.CreateColumnIfNotExists("Status", "Manual", "BOOLEAN", "BOOLEAN", "0")
   360  		sqlStore.CreateColumnIfNotExists("Status", "ActiveChannel", "varchar(26)", "varchar(26)", "")
   361  
   362  		saveSchemaVersion(sqlStore, Version340)
   363  	}
   364  }
   365  
   366  func upgradeDatabaseToVersion35(sqlStore *SqlStore) {
   367  	if shouldPerformUpgrade(sqlStore, Version340, Version350) {
   368  		sqlStore.GetMaster().ExecNoTimeout("UPDATE Users SET Roles = 'system_user' WHERE Roles = ''")
   369  		sqlStore.GetMaster().ExecNoTimeout("UPDATE Users SET Roles = 'system_user system_admin' WHERE Roles = 'system_admin'")
   370  		sqlStore.GetMaster().ExecNoTimeout("UPDATE TeamMembers SET Roles = 'team_user' WHERE Roles = ''")
   371  		sqlStore.GetMaster().ExecNoTimeout("UPDATE TeamMembers SET Roles = 'team_user team_admin' WHERE Roles = 'admin'")
   372  		sqlStore.GetMaster().ExecNoTimeout("UPDATE ChannelMembers SET Roles = 'channel_user' WHERE Roles = ''")
   373  		sqlStore.GetMaster().ExecNoTimeout("UPDATE ChannelMembers SET Roles = 'channel_user channel_admin' WHERE Roles = 'admin'")
   374  
   375  		// The rest of the migration from Filenames -> FileIds is done lazily in api.GetFileInfosForPost
   376  		sqlStore.CreateColumnIfNotExists("Posts", "FileIds", "varchar(150)", "varchar(150)", "[]")
   377  
   378  		// Increase maximum length of the Channel table Purpose column.
   379  		if sqlStore.GetMaxLengthOfColumnIfExists("Channels", "Purpose") != "250" {
   380  			sqlStore.AlterColumnTypeIfExists("Channels", "Purpose", "varchar(250)", "varchar(250)")
   381  		}
   382  
   383  		sqlStore.Session().RemoveAllSessions()
   384  
   385  		saveSchemaVersion(sqlStore, Version350)
   386  	}
   387  }
   388  
   389  func upgradeDatabaseToVersion36(sqlStore *SqlStore) {
   390  	if shouldPerformUpgrade(sqlStore, Version350, Version360) {
   391  		sqlStore.CreateColumnIfNotExists("Posts", "HasReactions", "tinyint", "boolean", "0")
   392  
   393  		// Add a Position column to users.
   394  		sqlStore.CreateColumnIfNotExists("Users", "Position", "varchar(64)", "varchar(64)", "")
   395  
   396  		// Remove ActiveChannel column from Status
   397  		sqlStore.RemoveColumnIfExists("Status", "ActiveChannel")
   398  
   399  		saveSchemaVersion(sqlStore, Version360)
   400  	}
   401  }
   402  
   403  func upgradeDatabaseToVersion37(sqlStore *SqlStore) {
   404  	if shouldPerformUpgrade(sqlStore, Version360, Version370) {
   405  		// Add EditAt column to Posts
   406  		sqlStore.CreateColumnIfNotExists("Posts", "EditAt", " bigint", " bigint", "0")
   407  
   408  		saveSchemaVersion(sqlStore, Version370)
   409  	}
   410  }
   411  
   412  func upgradeDatabaseToVersion38(sqlStore *SqlStore) {
   413  	if shouldPerformUpgrade(sqlStore, Version370, Version380) {
   414  		// Add the IsPinned column to posts.
   415  		sqlStore.CreateColumnIfNotExists("Posts", "IsPinned", "boolean", "boolean", "0")
   416  
   417  		saveSchemaVersion(sqlStore, Version380)
   418  	}
   419  }
   420  
   421  func upgradeDatabaseToVersion39(sqlStore *SqlStore) {
   422  	if shouldPerformUpgrade(sqlStore, Version380, Version390) {
   423  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE)
   424  		sqlStore.RemoveTableIfExists("PasswordRecovery")
   425  
   426  		saveSchemaVersion(sqlStore, Version390)
   427  	}
   428  }
   429  
   430  func upgradeDatabaseToVersion310(sqlStore *SqlStore) {
   431  	if shouldPerformUpgrade(sqlStore, Version390, Version3100) {
   432  		saveSchemaVersion(sqlStore, Version3100)
   433  	}
   434  }
   435  
   436  func upgradeDatabaseToVersion40(sqlStore *SqlStore) {
   437  	if shouldPerformUpgrade(sqlStore, Version3100, Version400) {
   438  		saveSchemaVersion(sqlStore, Version400)
   439  	}
   440  }
   441  
   442  func upgradeDatabaseToVersion41(sqlStore *SqlStore) {
   443  	if shouldPerformUpgrade(sqlStore, Version400, Version410) {
   444  		// Increase maximum length of the Users table Roles column.
   445  		if sqlStore.GetMaxLengthOfColumnIfExists("Users", "Roles") != "256" {
   446  			sqlStore.AlterColumnTypeIfExists("Users", "Roles", "varchar(256)", "varchar(256)")
   447  		}
   448  
   449  		sqlStore.RemoveTableIfExists("JobStatuses")
   450  
   451  		saveSchemaVersion(sqlStore, Version410)
   452  	}
   453  }
   454  
   455  func upgradeDatabaseToVersion42(sqlStore *SqlStore) {
   456  	if shouldPerformUpgrade(sqlStore, Version410, Version420) {
   457  		saveSchemaVersion(sqlStore, Version420)
   458  	}
   459  }
   460  
   461  func upgradeDatabaseToVersion43(sqlStore *SqlStore) {
   462  	if shouldPerformUpgrade(sqlStore, Version420, Version430) {
   463  		saveSchemaVersion(sqlStore, Version430)
   464  	}
   465  }
   466  
   467  func upgradeDatabaseToVersion44(sqlStore *SqlStore) {
   468  	if shouldPerformUpgrade(sqlStore, Version430, Version440) {
   469  		// Add the IsActive column to UserAccessToken.
   470  		sqlStore.CreateColumnIfNotExists("UserAccessTokens", "IsActive", "boolean", "boolean", "1")
   471  
   472  		saveSchemaVersion(sqlStore, Version440)
   473  	}
   474  }
   475  
   476  func upgradeDatabaseToVersion45(sqlStore *SqlStore) {
   477  	if shouldPerformUpgrade(sqlStore, Version440, Version450) {
   478  		saveSchemaVersion(sqlStore, Version450)
   479  	}
   480  }
   481  
   482  func upgradeDatabaseToVersion46(sqlStore *SqlStore) {
   483  	if shouldPerformUpgrade(sqlStore, Version450, Version460) {
   484  		sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
   485  		sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "")
   486  		saveSchemaVersion(sqlStore, Version460)
   487  	}
   488  }
   489  
   490  func upgradeDatabaseToVersion47(sqlStore *SqlStore) {
   491  	if shouldPerformUpgrade(sqlStore, Version460, Version470) {
   492  		sqlStore.AlterColumnTypeIfExists("Users", "Position", "varchar(128)", "varchar(128)")
   493  		sqlStore.AlterColumnTypeIfExists("OAuthAuthData", "State", "varchar(1024)", "varchar(1024)")
   494  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email")
   495  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Username")
   496  		saveSchemaVersion(sqlStore, Version470)
   497  	}
   498  }
   499  
   500  func upgradeDatabaseToVersion471(sqlStore *SqlStore) {
   501  	// If any new instances started with 4.7, they would have the bad Email column on the
   502  	// ChannelMemberHistory table. So for those cases we need to do an upgrade between
   503  	// 4.7.0 and 4.7.1
   504  	if shouldPerformUpgrade(sqlStore, Version470, Version471) {
   505  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email")
   506  		saveSchemaVersion(sqlStore, Version471)
   507  	}
   508  }
   509  
   510  func upgradeDatabaseToVersion472(sqlStore *SqlStore) {
   511  	if shouldPerformUpgrade(sqlStore, Version471, Version472) {
   512  		sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
   513  		saveSchemaVersion(sqlStore, Version472)
   514  	}
   515  }
   516  
   517  func upgradeDatabaseToVersion48(sqlStore *SqlStore) {
   518  	if shouldPerformUpgrade(sqlStore, Version472, Version480) {
   519  		saveSchemaVersion(sqlStore, Version480)
   520  	}
   521  }
   522  
   523  func upgradeDatabaseToVersion481(sqlStore *SqlStore) {
   524  	if shouldPerformUpgrade(sqlStore, Version480, Version481) {
   525  		sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
   526  		saveSchemaVersion(sqlStore, Version481)
   527  	}
   528  }
   529  
   530  func upgradeDatabaseToVersion49(sqlStore *SqlStore) {
   531  	// This version of Mattermost includes an App-Layer migration which migrates from hard-coded roles configured by
   532  	// a number of parameters in `config.json` to a `Roles` table in the database. The migration code can be seen
   533  	// in the file `app/app.go` in the function `DoAdvancedPermissionsMigration()`.
   534  
   535  	if shouldPerformUpgrade(sqlStore, Version481, Version490) {
   536  		defaultTimezone := timezones.DefaultUserTimezone()
   537  		defaultTimezoneValue, err := json.Marshal(defaultTimezone)
   538  		if err != nil {
   539  			mlog.Critical(err.Error())
   540  		}
   541  		sqlStore.CreateColumnIfNotExists("Users", "Timezone", "varchar(256)", "varchar(256)", string(defaultTimezoneValue))
   542  		sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
   543  		saveSchemaVersion(sqlStore, Version490)
   544  	}
   545  }
   546  
   547  func upgradeDatabaseToVersion410(sqlStore *SqlStore) {
   548  	if shouldPerformUpgrade(sqlStore, Version490, Version4100) {
   549  
   550  		sqlStore.RemoveIndexIfExists("Name_2", "Channels")
   551  		sqlStore.RemoveIndexIfExists("Name_2", "Emoji")
   552  		sqlStore.RemoveIndexIfExists("ClientId_2", "OAuthAccessData")
   553  
   554  		saveSchemaVersion(sqlStore, Version4100)
   555  		sqlStore.GetMaster().ExecNoTimeout("UPDATE Users SET AuthData=LOWER(AuthData) WHERE AuthService = 'saml'")
   556  	}
   557  }
   558  
   559  func upgradeDatabaseToVersion50(sqlStore *SqlStore) {
   560  	// This version of Mattermost includes an App-Layer migration which migrates from hard-coded emojis configured
   561  	// in `config.json` to a `Permission` in the database. The migration code can be seen
   562  	// in the file `app/app.go` in the function `DoEmojisPermissionsMigration()`.
   563  
   564  	// This version of Mattermost also includes a online-migration which migrates some roles from the `Roles` columns of
   565  	// TeamMember and ChannelMember rows to the new SchemeAdmin and SchemeUser columns. If you need to downgrade to a
   566  	// version of Mattermost prior to 5.0, you should take your server offline and run the following SQL statements
   567  	// prior to launching the downgraded version:
   568  	//
   569  	//    UPDATE Teams SET SchemeId = NULL;
   570  	//    UPDATE Channels SET SchemeId = NULL;
   571  	//    UPDATE TeamMembers SET Roles = CONCAT(Roles, ' team_user'), SchemeUser = NULL where SchemeUser = 1;
   572  	//    UPDATE TeamMembers SET Roles = CONCAT(Roles, ' team_admin'), SchemeAdmin = NULL where SchemeAdmin = 1;
   573  	//    UPDATE ChannelMembers SET Roles = CONCAT(Roles, ' channel_user'), SchemeUser = NULL where SchemeUser = 1;
   574  	//    UPDATE ChannelMembers SET Roles = CONCAT(Roles, ' channel_admin'), SchemeAdmin = NULL where SchemeAdmin = 1;
   575  	//    DELETE from Systems WHERE Name = 'migration_advanced_permissions_phase_2';
   576  
   577  	if shouldPerformUpgrade(sqlStore, Version4100, Version500) {
   578  		sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "SchemeId", "varchar(26)", "varchar(26)")
   579  
   580  		sqlStore.CreateColumnIfNotExistsNoDefault("ChannelMembers", "SchemeUser", "boolean", "boolean")
   581  		sqlStore.CreateColumnIfNotExistsNoDefault("ChannelMembers", "SchemeAdmin", "boolean", "boolean")
   582  
   583  		sqlStore.CreateColumnIfNotExists("Roles", "BuiltIn", "boolean", "boolean", "0")
   584  		sqlStore.GetMaster().ExecNoTimeout("UPDATE Roles SET BuiltIn=true")
   585  		sqlStore.GetMaster().ExecNoTimeout("UPDATE Roles SET SchemeManaged=false WHERE Name NOT IN ('system_user', 'system_admin', 'team_user', 'team_admin', 'channel_user', 'channel_admin')")
   586  		sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "ChannelLocked", "boolean", "boolean", "0")
   587  
   588  		sqlStore.RemoveIndexIfExists("idx_channels_txt", "Channels")
   589  
   590  		saveSchemaVersion(sqlStore, Version500)
   591  	}
   592  }
   593  
   594  func upgradeDatabaseToVersion51(sqlStore *SqlStore) {
   595  	if shouldPerformUpgrade(sqlStore, Version500, Version510) {
   596  		saveSchemaVersion(sqlStore, Version510)
   597  	}
   598  }
   599  
   600  func upgradeDatabaseToVersion52(sqlStore *SqlStore) {
   601  	if shouldPerformUpgrade(sqlStore, Version510, Version520) {
   602  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
   603  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "")
   604  		saveSchemaVersion(sqlStore, Version520)
   605  	}
   606  }
   607  
   608  func upgradeDatabaseToVersion53(sqlStore *SqlStore) {
   609  	if shouldPerformUpgrade(sqlStore, Version520, Version530) {
   610  		saveSchemaVersion(sqlStore, Version530)
   611  	}
   612  }
   613  
   614  func upgradeDatabaseToVersion54(sqlStore *SqlStore) {
   615  	if shouldPerformUpgrade(sqlStore, Version530, Version540) {
   616  		sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "Description", "varchar(500)", "varchar(500)")
   617  		sqlStore.AlterColumnTypeIfExists("IncomingWebhooks", "Description", "varchar(500)", "varchar(500)")
   618  		if err := sqlStore.Channel().MigratePublicChannels(); err != nil {
   619  			mlog.Critical("Failed to migrate PublicChannels table", mlog.Err(err))
   620  			time.Sleep(time.Second)
   621  			os.Exit(ExitGenericFailure)
   622  		}
   623  		saveSchemaVersion(sqlStore, Version540)
   624  	}
   625  }
   626  
   627  func upgradeDatabaseToVersion55(sqlStore *SqlStore) {
   628  	if shouldPerformUpgrade(sqlStore, Version540, Version550) {
   629  		saveSchemaVersion(sqlStore, Version550)
   630  	}
   631  }
   632  
   633  func upgradeDatabaseToVersion56(sqlStore *SqlStore) {
   634  	if shouldPerformUpgrade(sqlStore, Version550, Version560) {
   635  		sqlStore.CreateColumnIfNotExists("PluginKeyValueStore", "ExpireAt", "bigint(20)", "bigint", "0")
   636  
   637  		// migrating user's accepted terms of service data into the new table
   638  		sqlStore.GetMaster().ExecNoTimeout("INSERT INTO UserTermsOfService SELECT Id, AcceptedTermsOfServiceId as TermsOfServiceId, :CreateAt FROM Users WHERE AcceptedTermsOfServiceId != \"\" AND AcceptedTermsOfServiceId IS NOT NULL", map[string]interface{}{"CreateAt": model.GetMillis()})
   639  
   640  		if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   641  			sqlStore.RemoveIndexIfExists("idx_users_email_lower", "lower(Email)")
   642  			sqlStore.RemoveIndexIfExists("idx_users_username_lower", "lower(Username)")
   643  			sqlStore.RemoveIndexIfExists("idx_users_nickname_lower", "lower(Nickname)")
   644  			sqlStore.RemoveIndexIfExists("idx_users_firstname_lower", "lower(FirstName)")
   645  			sqlStore.RemoveIndexIfExists("idx_users_lastname_lower", "lower(LastName)")
   646  		}
   647  
   648  		saveSchemaVersion(sqlStore, Version560)
   649  	}
   650  
   651  }
   652  
   653  func upgradeDatabaseToVersion57(sqlStore *SqlStore) {
   654  	if shouldPerformUpgrade(sqlStore, Version560, Version570) {
   655  		saveSchemaVersion(sqlStore, Version570)
   656  	}
   657  }
   658  
   659  func upgradeDatabaseToVersion58(sqlStore *SqlStore) {
   660  	if shouldPerformUpgrade(sqlStore, Version570, Version580) {
   661  		// idx_channels_txt was removed in `upgradeDatabaseToVersion50`, but merged as part of
   662  		// v5.1, so the migration wouldn't apply to anyone upgrading from v5.0. Remove it again to
   663  		// bring the upgraded (from v5.0) and fresh install schemas back in sync.
   664  		sqlStore.RemoveIndexIfExists("idx_channels_txt", "Channels")
   665  
   666  		// Fix column types and defaults where gorp converged on a different schema value than the
   667  		// original migration.
   668  		sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "Description", "text", "VARCHAR(500)")
   669  		sqlStore.AlterColumnTypeIfExists("IncomingWebhooks", "Description", "text", "VARCHAR(500)")
   670  		sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "IconURL", "text", "VARCHAR(1024)")
   671  		sqlStore.RemoveDefaultIfColumnExists("OutgoingWebhooks", "Username")
   672  		if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   673  			sqlStore.RemoveDefaultIfColumnExists("OutgoingWebhooks", "IconURL")
   674  		}
   675  		sqlStore.AlterDefaultIfColumnExists("OutgoingWebhooks", "Username", model.NewString("NULL"), nil)
   676  		sqlStore.AlterDefaultIfColumnExists("PluginKeyValueStore", "ExpireAt", model.NewString("NULL"), model.NewString("NULL"))
   677  
   678  		saveSchemaVersion(sqlStore, Version580)
   679  	}
   680  }
   681  
   682  func upgradeDatabaseToVersion59(sqlStore *SqlStore) {
   683  	if shouldPerformUpgrade(sqlStore, Version580, Version590) {
   684  		saveSchemaVersion(sqlStore, Version590)
   685  	}
   686  }
   687  
   688  func upgradeDatabaseToVersion510(sqlStore *SqlStore) {
   689  	if shouldPerformUpgrade(sqlStore, Version590, Version5100) {
   690  		sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(4)", "boolean")
   691  
   692  		sqlStore.CreateIndexIfNotExists("idx_groupteams_teamid", "GroupTeams", "TeamId")
   693  		sqlStore.CreateIndexIfNotExists("idx_groupchannels_channelid", "GroupChannels", "ChannelId")
   694  
   695  		saveSchemaVersion(sqlStore, Version5100)
   696  	}
   697  }
   698  
   699  func upgradeDatabaseToVersion511(sqlStore *SqlStore) {
   700  	if shouldPerformUpgrade(sqlStore, Version5100, Version5110) {
   701  		// Enforce all teams have an InviteID set
   702  		var teams []*model.Team
   703  		if _, err := sqlStore.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE InviteId = ''"); err != nil {
   704  			mlog.Error("Error fetching Teams without InviteID", mlog.Err(err))
   705  		} else {
   706  			for _, team := range teams {
   707  				team.InviteId = model.NewId()
   708  				if _, err := sqlStore.Team().Update(team); err != nil {
   709  					mlog.Error("Error updating Team InviteIDs", mlog.String("team_id", team.Id), mlog.Err(err))
   710  				}
   711  			}
   712  		}
   713  
   714  		saveSchemaVersion(sqlStore, Version5110)
   715  	}
   716  }
   717  
   718  func upgradeDatabaseToVersion512(sqlStore *SqlStore) {
   719  	if shouldPerformUpgrade(sqlStore, Version5110, Version5120) {
   720  		sqlStore.CreateColumnIfNotExistsNoDefault("ChannelMembers", "SchemeGuest", "boolean", "boolean")
   721  		sqlStore.CreateColumnIfNotExistsNoDefault("Schemes", "DefaultTeamGuestRole", "text", "VARCHAR(64)")
   722  		sqlStore.CreateColumnIfNotExistsNoDefault("Schemes", "DefaultChannelGuestRole", "text", "VARCHAR(64)")
   723  
   724  		sqlStore.GetMaster().ExecNoTimeout("UPDATE Schemes SET DefaultTeamGuestRole = '', DefaultChannelGuestRole = ''")
   725  
   726  		// Saturday, January 24, 2065 5:20:00 AM GMT. To remove all personal access token sessions.
   727  		sqlStore.GetMaster().ExecNoTimeout("DELETE FROM Sessions WHERE ExpiresAt > 3000000000000")
   728  
   729  		saveSchemaVersion(sqlStore, Version5120)
   730  	}
   731  }
   732  
   733  func upgradeDatabaseToVersion513(sqlStore *SqlStore) {
   734  	if shouldPerformUpgrade(sqlStore, Version5120, Version5130) {
   735  		// The previous jobs ran once per minute, cluttering the Jobs table with somewhat useless entries. Clean that up.
   736  		sqlStore.GetMaster().ExecNoTimeout("DELETE FROM Jobs WHERE Type = 'plugins'")
   737  
   738  		saveSchemaVersion(sqlStore, Version5130)
   739  	}
   740  }
   741  
   742  func upgradeDatabaseToVersion514(sqlStore *SqlStore) {
   743  	if shouldPerformUpgrade(sqlStore, Version5130, Version5140) {
   744  		saveSchemaVersion(sqlStore, Version5140)
   745  	}
   746  }
   747  
   748  func upgradeDatabaseToVersion515(sqlStore *SqlStore) {
   749  	if shouldPerformUpgrade(sqlStore, Version5140, Version5150) {
   750  		saveSchemaVersion(sqlStore, Version5150)
   751  	}
   752  }
   753  
   754  func upgradeDatabaseToVersion516(sqlStore *SqlStore) {
   755  	if shouldPerformUpgrade(sqlStore, Version5150, Version5160) {
   756  		if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   757  			sqlStore.GetMaster().ExecNoTimeout("ALTER TABLE Tokens ALTER COLUMN Extra TYPE varchar(2048)")
   758  		} else if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
   759  			sqlStore.GetMaster().ExecNoTimeout("ALTER TABLE Tokens MODIFY Extra text")
   760  		}
   761  		saveSchemaVersion(sqlStore, Version5160)
   762  
   763  		// Fix mismatches between the canonical and migrated schemas.
   764  		sqlStore.AlterColumnTypeIfExists("Schemes", "DefaultTeamGuestRole", "varchar(64)", "VARCHAR(64)")
   765  		sqlStore.AlterColumnTypeIfExists("Schemes", "DefaultChannelGuestRole", "varchar(64)", "VARCHAR(64)")
   766  		sqlStore.AlterColumnTypeIfExists("Teams", "AllowedDomains", "text", "VARCHAR(1000)")
   767  		sqlStore.AlterColumnTypeIfExists("Channels", "GroupConstrained", "tinyint(1)", "boolean")
   768  		sqlStore.AlterColumnTypeIfExists("Teams", "GroupConstrained", "tinyint(1)", "boolean")
   769  
   770  		// One known mismatch remains: ChannelMembers.SchemeGuest. The requisite migration
   771  		// is left here for posterity, but we're avoiding fix this given the corresponding
   772  		// table rewrite in most MySQL and Postgres instances.
   773  		// sqlStore.AlterColumnTypeIfExists("ChannelMembers", "SchemeGuest", "tinyint(4)", "boolean")
   774  
   775  		sqlStore.CreateIndexIfNotExists("idx_groupteams_teamid", "GroupTeams", "TeamId")
   776  		sqlStore.CreateIndexIfNotExists("idx_groupchannels_channelid", "GroupChannels", "ChannelId")
   777  	}
   778  }
   779  
   780  func upgradeDatabaseToVersion517(sqlStore *SqlStore) {
   781  	if shouldPerformUpgrade(sqlStore, Version5160, Version5170) {
   782  		saveSchemaVersion(sqlStore, Version5170)
   783  	}
   784  }
   785  
   786  func upgradeDatabaseToVersion518(sqlStore *SqlStore) {
   787  	if shouldPerformUpgrade(sqlStore, Version5170, Version5180) {
   788  		saveSchemaVersion(sqlStore, Version5180)
   789  	}
   790  }
   791  
   792  func upgradeDatabaseToVersion519(sqlStore *SqlStore) {
   793  	if shouldPerformUpgrade(sqlStore, Version5180, Version5190) {
   794  		saveSchemaVersion(sqlStore, Version5190)
   795  	}
   796  }
   797  
   798  func upgradeDatabaseToVersion520(sqlStore *SqlStore) {
   799  	if shouldPerformUpgrade(sqlStore, Version5190, Version5200) {
   800  		sqlStore.CreateColumnIfNotExistsNoDefault("Bots", "LastIconUpdate", "bigint", "bigint")
   801  
   802  		sqlStore.CreateColumnIfNotExists("GroupTeams", "SchemeAdmin", "boolean", "boolean", "0")
   803  		sqlStore.CreateIndexIfNotExists("idx_groupteams_schemeadmin", "GroupTeams", "SchemeAdmin")
   804  
   805  		sqlStore.CreateColumnIfNotExists("GroupChannels", "SchemeAdmin", "boolean", "boolean", "0")
   806  		sqlStore.CreateIndexIfNotExists("idx_groupchannels_schemeadmin", "GroupChannels", "SchemeAdmin")
   807  
   808  		saveSchemaVersion(sqlStore, Version5200)
   809  	}
   810  }
   811  
   812  func upgradeDatabaseToVersion521(sqlStore *SqlStore) {
   813  	if shouldPerformUpgrade(sqlStore, Version5200, Version5210) {
   814  		saveSchemaVersion(sqlStore, Version5210)
   815  	}
   816  }
   817  
   818  func upgradeDatabaseToVersion522(sqlStore *SqlStore) {
   819  	if shouldPerformUpgrade(sqlStore, Version5210, Version5220) {
   820  		sqlStore.CreateIndexIfNotExists("idx_teams_scheme_id", "Teams", "SchemeId")
   821  		sqlStore.CreateIndexIfNotExists("idx_channels_scheme_id", "Channels", "SchemeId")
   822  		sqlStore.CreateIndexIfNotExists("idx_channels_scheme_id", "Channels", "SchemeId")
   823  		sqlStore.CreateIndexIfNotExists("idx_schemes_channel_guest_role", "Schemes", "DefaultChannelGuestRole")
   824  		sqlStore.CreateIndexIfNotExists("idx_schemes_channel_user_role", "Schemes", "DefaultChannelUserRole")
   825  		sqlStore.CreateIndexIfNotExists("idx_schemes_channel_admin_role", "Schemes", "DefaultChannelAdminRole")
   826  
   827  		saveSchemaVersion(sqlStore, Version5220)
   828  	}
   829  }
   830  
   831  func upgradeDatabaseToVersion523(sqlStore *SqlStore) {
   832  	if shouldPerformUpgrade(sqlStore, Version5220, Version5230) {
   833  		saveSchemaVersion(sqlStore, Version5230)
   834  	}
   835  }
   836  
   837  func upgradeDatabaseToVersion524(sqlStore *SqlStore) {
   838  	if shouldPerformUpgrade(sqlStore, Version5230, Version5240) {
   839  		sqlStore.CreateColumnIfNotExists("UserGroups", "AllowReference", "boolean", "boolean", "0")
   840  		sqlStore.GetMaster().ExecNoTimeout("UPDATE UserGroups SET Name = null, AllowReference = false")
   841  		sqlStore.AlterPrimaryKey("Reactions", []string{"PostId", "UserId", "EmojiName"})
   842  
   843  		saveSchemaVersion(sqlStore, Version5240)
   844  	}
   845  }
   846  
   847  func upgradeDatabaseToVersion525(sqlStore *SqlStore) {
   848  	if shouldPerformUpgrade(sqlStore, Version5240, Version5250) {
   849  		saveSchemaVersion(sqlStore, Version5250)
   850  	}
   851  }
   852  
   853  func upgradeDatabaseToVersion526(sqlStore *SqlStore) {
   854  	if shouldPerformUpgrade(sqlStore, Version5250, Version5260) {
   855  		sqlStore.CreateColumnIfNotExists("Sessions", "ExpiredNotify", "boolean", "boolean", "0")
   856  
   857  		saveSchemaVersion(sqlStore, Version5260)
   858  	}
   859  }
   860  
   861  func upgradeDatabaseToVersion527(sqlStore *SqlStore) {
   862  	if shouldPerformUpgrade(sqlStore, Version5260, Version5270) {
   863  		saveSchemaVersion(sqlStore, Version5270)
   864  	}
   865  }
   866  
   867  func upgradeDatabaseToVersion528(sqlStore *SqlStore) {
   868  	if shouldPerformUpgrade(sqlStore, Version5270, Version5280) {
   869  		if err := precheckMigrationToVersion528(sqlStore); err != nil {
   870  			mlog.Critical("Error upgrading DB schema to 5.28.0", mlog.Err(err))
   871  			os.Exit(ExitGenericFailure)
   872  		}
   873  
   874  		sqlStore.CreateColumnIfNotExistsNoDefault("Commands", "PluginId", "VARCHAR(190)", "VARCHAR(190)")
   875  		sqlStore.GetMaster().ExecNoTimeout("UPDATE Commands SET PluginId = '' WHERE PluginId IS NULL")
   876  
   877  		sqlStore.AlterColumnTypeIfExists("Teams", "Type", "VARCHAR(255)", "VARCHAR(255)")
   878  		sqlStore.AlterColumnTypeIfExists("Teams", "SchemeId", "VARCHAR(26)", "VARCHAR(26)")
   879  		sqlStore.AlterColumnTypeIfExists("IncomingWebhooks", "Username", "varchar(255)", "varchar(255)")
   880  		sqlStore.AlterColumnTypeIfExists("IncomingWebhooks", "IconURL", "text", "varchar(1024)")
   881  
   882  		saveSchemaVersion(sqlStore, Version5280)
   883  	}
   884  }
   885  
   886  func upgradeDatabaseToVersion5281(sqlStore *SqlStore) {
   887  	if shouldPerformUpgrade(sqlStore, Version5280, Version5281) {
   888  		sqlStore.CreateColumnIfNotExistsNoDefault("FileInfo", "MiniPreview", "MEDIUMBLOB", "bytea")
   889  
   890  		saveSchemaVersion(sqlStore, Version5281)
   891  	}
   892  }
   893  
   894  func precheckMigrationToVersion528(sqlStore *SqlStore) error {
   895  	teamsQuery, _, err := sqlStore.getQueryBuilder().Select(`COALESCE(SUM(CASE
   896  				WHEN CHAR_LENGTH(SchemeId) > 26 THEN 1
   897  				ELSE 0
   898  			END),0) as schemeidwrong,
   899  			COALESCE(SUM(CASE
   900  				WHEN CHAR_LENGTH(Type) > 255 THEN 1
   901  				ELSE 0
   902  			END),0) as typewrong`).
   903  		From("Teams").ToSql()
   904  	if err != nil {
   905  		return err
   906  	}
   907  	webhooksQuery, _, err := sqlStore.getQueryBuilder().Select(`COALESCE(SUM(CASE
   908  				WHEN CHAR_LENGTH(Username) > 255 THEN 1
   909  				ELSE 0
   910  			END),0) as usernamewrong,
   911  			COALESCE(SUM(CASE
   912  				WHEN CHAR_LENGTH(IconURL) > 1024 THEN 1
   913  				ELSE 0
   914  			END),0) as iconurlwrong`).
   915  		From("IncomingWebhooks").ToSql()
   916  	if err != nil {
   917  		return err
   918  	}
   919  
   920  	var schemeIDWrong, typeWrong int
   921  	row := sqlStore.GetMaster().Db.QueryRow(teamsQuery)
   922  	if err = row.Scan(&schemeIDWrong, &typeWrong); err != nil && err != sql.ErrNoRows {
   923  		return err
   924  	} else if err == nil && schemeIDWrong > 0 {
   925  		return errors.New("Migration failure: " +
   926  			"Teams column SchemeId has data larger that 26 characters")
   927  	} else if err == nil && typeWrong > 0 {
   928  		return errors.New("Migration failure: " +
   929  			"Teams column Type has data larger that 255 characters")
   930  	}
   931  
   932  	var usernameWrong, iconURLWrong int
   933  	row = sqlStore.GetMaster().Db.QueryRow(webhooksQuery)
   934  	if err = row.Scan(&usernameWrong, &iconURLWrong); err != nil && err != sql.ErrNoRows {
   935  		mlog.Error("Error fetching IncomingWebhooks columns data", mlog.Err(err))
   936  	} else if err == nil && usernameWrong > 0 {
   937  		return errors.New("Migration failure: " +
   938  			"IncomingWebhooks column Username has data larger that 255 characters")
   939  	} else if err == nil && iconURLWrong > 0 {
   940  		return errors.New("Migration failure: " +
   941  			"IncomingWebhooks column IconURL has data larger that 1024 characters")
   942  	}
   943  
   944  	return nil
   945  }
   946  
   947  func upgradeDatabaseToVersion529(sqlStore *SqlStore) {
   948  	if hasMissingMigrationsVersion529(sqlStore) {
   949  		mlog.Info("Applying migrations for version 5.29")
   950  		sqlStore.AlterColumnTypeIfExists("SidebarCategories", "Id", "VARCHAR(128)", "VARCHAR(128)")
   951  		sqlStore.RemoveDefaultIfColumnExists("SidebarCategories", "Id")
   952  		sqlStore.AlterColumnTypeIfExists("SidebarChannels", "CategoryId", "VARCHAR(128)", "VARCHAR(128)")
   953  		sqlStore.RemoveDefaultIfColumnExists("SidebarChannels", "CategoryId")
   954  
   955  		sqlStore.CreateColumnIfNotExistsNoDefault("Threads", "ChannelId", "VARCHAR(26)", "VARCHAR(26)")
   956  
   957  		updateThreadChannelsQuery := "UPDATE Threads INNER JOIN Posts ON Posts.Id=Threads.PostId SET Threads.ChannelId=Posts.ChannelId WHERE Threads.ChannelId IS NULL"
   958  		if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   959  			updateThreadChannelsQuery = "UPDATE Threads SET ChannelId=Posts.ChannelId FROM Posts WHERE Posts.Id=Threads.PostId AND Threads.ChannelId IS NULL"
   960  		}
   961  		if _, err := sqlStore.GetMaster().ExecNoTimeout(updateThreadChannelsQuery); err != nil {
   962  			mlog.Error("Error updating ChannelId in Threads table", mlog.Err(err))
   963  		}
   964  	}
   965  
   966  	if shouldPerformUpgrade(sqlStore, Version5281, Version5290) {
   967  		saveSchemaVersion(sqlStore, Version5290)
   968  	}
   969  }
   970  
   971  func hasMissingMigrationsVersion529(sqlStore *SqlStore) bool {
   972  	scIdInfo, err := sqlStore.GetColumnInfo("SidebarCategories", "Id")
   973  	if err != nil {
   974  		mlog.Error("Error getting column info for migration check",
   975  			mlog.String("table", "SidebarCategories"),
   976  			mlog.String("column", "Id"),
   977  			mlog.Err(err),
   978  		)
   979  		return true
   980  	}
   981  	if !sqlStore.IsVarchar(scIdInfo.DataType) || scIdInfo.CharMaximumLength != 128 {
   982  		return true
   983  	}
   984  	scCategoryIdInfo, err := sqlStore.GetColumnInfo("SidebarChannels", "CategoryId")
   985  	if err != nil {
   986  		mlog.Error("Error getting column info for migration check",
   987  			mlog.String("table", "SidebarChannels"),
   988  			mlog.String("column", "CategoryId"),
   989  			mlog.Err(err),
   990  		)
   991  		return true
   992  	}
   993  	if !sqlStore.IsVarchar(scCategoryIdInfo.DataType) || scCategoryIdInfo.CharMaximumLength != 128 {
   994  		return true
   995  	}
   996  	if !sqlStore.DoesColumnExist("Threads", "ChannelId") {
   997  		return true
   998  	}
   999  	return false
  1000  }
  1001  
  1002  func upgradeDatabaseToVersion5291(sqlStore *SqlStore) {
  1003  	if shouldPerformUpgrade(sqlStore, Version5290, Version5291) {
  1004  		saveSchemaVersion(sqlStore, Version5291)
  1005  	}
  1006  }
  1007  
  1008  func upgradeDatabaseToVersion530(sqlStore *SqlStore) {
  1009  	if hasMissingMigrationsVersion530(sqlStore) {
  1010  		mlog.Info("Applying migrations for version 5.30")
  1011  		sqlStore.CreateColumnIfNotExistsNoDefault("FileInfo", "Content", "longtext", "text")
  1012  		sqlStore.CreateColumnIfNotExists("SidebarCategories", "Muted", "tinyint(1)", "boolean", "0")
  1013  	}
  1014  	if shouldPerformUpgrade(sqlStore, Version5291, Version5300) {
  1015  		saveSchemaVersion(sqlStore, Version5300)
  1016  	}
  1017  }
  1018  
  1019  func hasMissingMigrationsVersion530(sqlStore *SqlStore) bool {
  1020  	if !sqlStore.DoesColumnExist("FileInfo", "Content") {
  1021  		return true
  1022  	}
  1023  	if !sqlStore.DoesColumnExist("SidebarCategories", "Muted") {
  1024  		return true
  1025  	}
  1026  	return false
  1027  }
  1028  
  1029  func upgradeDatabaseToVersion531(sqlStore *SqlStore) {
  1030  	if shouldPerformUpgrade(sqlStore, Version5300, Version5310) {
  1031  		saveSchemaVersion(sqlStore, Version5310)
  1032  	}
  1033  }
  1034  
  1035  const RemoteClusterSiteURLUniqueIndex = "remote_clusters_site_url_unique"
  1036  
  1037  func upgradeDatabaseToVersion532(sqlStore *SqlStore) {
  1038  	if hasMissingMigrationsVersion532(sqlStore) {
  1039  		// this migration was reverted on MySQL due to performance reasons. Doing
  1040  		// it only on PostgreSQL for the time being.
  1041  		if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  1042  			// allow 10 files per post
  1043  			sqlStore.AlterColumnTypeIfExists("Posts", "FileIds", "text", "varchar(300)")
  1044  		}
  1045  
  1046  		sqlStore.CreateColumnIfNotExists("ThreadMemberships", "UnreadMentions", "bigint", "bigint", "0")
  1047  		// Shared channels support
  1048  		sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "Shared", "tinyint(1)", "boolean")
  1049  		sqlStore.CreateColumnIfNotExistsNoDefault("Reactions", "UpdateAt", "bigint", "bigint")
  1050  		sqlStore.CreateColumnIfNotExistsNoDefault("Reactions", "DeleteAt", "bigint", "bigint")
  1051  	}
  1052  
  1053  	if shouldPerformUpgrade(sqlStore, Version5310, Version5320) {
  1054  		saveSchemaVersion(sqlStore, Version5320)
  1055  	}
  1056  }
  1057  
  1058  func hasMissingMigrationsVersion532(sqlStore *SqlStore) bool {
  1059  	scIdInfo, err := sqlStore.GetColumnInfo("Posts", "FileIds")
  1060  	if err != nil {
  1061  		mlog.Error("Error getting column info for migration check",
  1062  			mlog.String("table", "Posts"),
  1063  			mlog.String("column", "FileIds"),
  1064  			mlog.Err(err),
  1065  		)
  1066  		return true
  1067  	}
  1068  
  1069  	if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  1070  		if !sqlStore.IsVarchar(scIdInfo.DataType) || scIdInfo.CharMaximumLength != 300 {
  1071  			return true
  1072  		}
  1073  	}
  1074  
  1075  	if !sqlStore.DoesColumnExist("Channels", "Shared") {
  1076  		return true
  1077  	}
  1078  
  1079  	if !sqlStore.DoesColumnExist("ThreadMemberships", "UnreadMentions") {
  1080  		return true
  1081  	}
  1082  
  1083  	if !sqlStore.DoesColumnExist("Reactions", "UpdateAt") {
  1084  		return true
  1085  	}
  1086  
  1087  	if !sqlStore.DoesColumnExist("Reactions", "DeleteAt") {
  1088  		return true
  1089  	}
  1090  
  1091  	return false
  1092  }
  1093  
  1094  func upgradeDatabaseToVersion533(sqlStore *SqlStore) {
  1095  	if shouldPerformUpgrade(sqlStore, Version5320, Version5330) {
  1096  		saveSchemaVersion(sqlStore, Version5330)
  1097  	}
  1098  }
  1099  
  1100  func upgradeDatabaseToVersion534(sqlStore *SqlStore) {
  1101  	if shouldPerformUpgrade(sqlStore, Version5330, Version5340) {
  1102  		saveSchemaVersion(sqlStore, Version5340)
  1103  	}
  1104  }
  1105  
  1106  func upgradeDatabaseToVersion535(sqlStore *SqlStore) {
  1107  	if hasMissingMigrationsVersion535(sqlStore) {
  1108  		sqlStore.AlterColumnTypeIfExists("Roles", "Permissions", "longtext", "text")
  1109  
  1110  		sqlStore.CreateColumnIfNotExists("SidebarCategories", "Collapsed", "tinyint(1)", "boolean", "0")
  1111  
  1112  		// Shared channels support
  1113  		sqlStore.CreateColumnIfNotExistsNoDefault("Reactions", "RemoteId", "VARCHAR(26)", "VARCHAR(26)")
  1114  		sqlStore.CreateColumnIfNotExistsNoDefault("Users", "RemoteId", "VARCHAR(26)", "VARCHAR(26)")
  1115  		sqlStore.CreateColumnIfNotExistsNoDefault("Posts", "RemoteId", "VARCHAR(26)", "VARCHAR(26)")
  1116  		sqlStore.CreateColumnIfNotExistsNoDefault("FileInfo", "RemoteId", "VARCHAR(26)", "VARCHAR(26)")
  1117  		sqlStore.CreateColumnIfNotExists("UploadSessions", "RemoteId", "VARCHAR(26)", "VARCHAR(26)", "")
  1118  		sqlStore.CreateColumnIfNotExists("UploadSessions", "ReqFileId", "VARCHAR(26)", "VARCHAR(26)", "")
  1119  
  1120  		if _, err := sqlStore.GetMaster().ExecNoTimeout("UPDATE UploadSessions SET RemoteId='', ReqFileId='' WHERE RemoteId IS NULL"); err != nil {
  1121  			mlog.Error("Error updating RemoteId,ReqFileId in UploadsSession table", mlog.Err(err))
  1122  		}
  1123  		uniquenessColumns := []string{"SiteUrl", "RemoteTeamId"}
  1124  		if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1125  			uniquenessColumns = []string{"RemoteTeamId", "SiteUrl(168)"}
  1126  		}
  1127  		sqlStore.CreateUniqueCompositeIndexIfNotExists(RemoteClusterSiteURLUniqueIndex, "RemoteClusters", uniquenessColumns)
  1128  		sqlStore.CreateColumnIfNotExists("SharedChannelUsers", "ChannelId", "VARCHAR(26)", "VARCHAR(26)", "")
  1129  
  1130  		rootCountMigration(sqlStore)
  1131  	}
  1132  
  1133  	if shouldPerformUpgrade(sqlStore, Version5340, Version5350) {
  1134  		saveSchemaVersion(sqlStore, Version5350)
  1135  	}
  1136  }
  1137  
  1138  func rootCountMigration(sqlStore *SqlStore) {
  1139  	totalMsgCountRootExists := sqlStore.DoesColumnExist("Channels", "TotalMsgCountRoot")
  1140  	msgCountRootExists := sqlStore.DoesColumnExist("ChannelMembers", "MsgCountRoot")
  1141  
  1142  	sqlStore.CreateColumnIfNotExists("ChannelMembers", "MentionCountRoot", "bigint", "bigint", "0")
  1143  	sqlStore.AlterDefaultIfColumnExists("ChannelMembers", "MentionCountRoot", model.NewString("0"), model.NewString("0"))
  1144  
  1145  	mentionCountRootCTE := `
  1146  		SELECT ChannelId, COALESCE(SUM(UnreadMentions), 0) AS UnreadMentions, UserId
  1147  		FROM ThreadMemberships
  1148  		LEFT JOIN Threads ON ThreadMemberships.PostId = Threads.PostId
  1149  		GROUP BY Threads.ChannelId, ThreadMemberships.UserId
  1150  	`
  1151  	updateMentionCountRootQuery := `
  1152  		UPDATE ChannelMembers INNER JOIN (` + mentionCountRootCTE + `) AS q ON
  1153  			q.ChannelId = ChannelMembers.ChannelId AND
  1154  			q.UserId=ChannelMembers.UserId AND
  1155  			ChannelMembers.MentionCount > 0
  1156  		SET MentionCountRoot = ChannelMembers.MentionCount - q.UnreadMentions
  1157  	`
  1158  	if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  1159  		updateMentionCountRootQuery = `
  1160  			WITH q AS (` + mentionCountRootCTE + `)
  1161  			UPDATE channelmembers
  1162  			SET MentionCountRoot = ChannelMembers.MentionCount - q.UnreadMentions
  1163  			FROM q
  1164  			WHERE
  1165  				q.ChannelId = ChannelMembers.ChannelId AND
  1166  				q.UserId = ChannelMembers.UserId AND
  1167  				ChannelMembers.MentionCount > 0
  1168  		`
  1169  	}
  1170  	if _, err := sqlStore.GetMaster().ExecNoTimeout(updateMentionCountRootQuery); err != nil {
  1171  		mlog.Error("Error updating ChannelId in Threads table", mlog.Err(err))
  1172  	}
  1173  	sqlStore.CreateColumnIfNotExists("Channels", "TotalMsgCountRoot", "bigint", "bigint", "0")
  1174  	sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "LastRootPostAt", "bigint", "bigint")
  1175  	defer sqlStore.RemoveColumnIfExists("Channels", "LastRootPostAt")
  1176  
  1177  	sqlStore.CreateColumnIfNotExists("ChannelMembers", "MsgCountRoot", "bigint", "bigint", "0")
  1178  	sqlStore.AlterDefaultIfColumnExists("ChannelMembers", "MsgCountRoot", model.NewString("0"), model.NewString("0"))
  1179  
  1180  	forceIndex := ""
  1181  	if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1182  		forceIndex = "FORCE INDEX(idx_posts_channel_id_update_at)"
  1183  	}
  1184  	totalMsgCountRootCTE := `
  1185  	SELECT Channels.Id channelid, COALESCE(COUNT(*),0) newcount, COALESCE(MAX(Posts.CreateAt), 0) as lastpost
  1186  	FROM Channels
  1187  	LEFT JOIN Posts ` + forceIndex + ` ON Channels.Id = Posts.ChannelId
  1188  	WHERE Posts.RootId = ''
  1189  	GROUP BY Channels.Id
  1190  `
  1191  	channelsCTE := "SELECT TotalMsgCountRoot, Id, LastRootPostAt from Channels"
  1192  	updateChannels := `
  1193  	WITH q AS (` + totalMsgCountRootCTE + `)
  1194  	UPDATE Channels SET TotalMsgCountRoot = q.newcount, LastRootPostAt=q.lastpost
  1195  	FROM q where q.channelid=Channels.Id;
  1196  `
  1197  	updateChannelMembers := `
  1198  	WITH q as (` + channelsCTE + `)
  1199  	UPDATE ChannelMembers CM SET MsgCountRoot=TotalMsgCountRoot
  1200  	FROM q WHERE q.id=CM.ChannelId AND LastViewedAt >= q.lastrootpostat;
  1201  `
  1202  	if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1203  		updateChannels = `
  1204  		UPDATE Channels
  1205  		INNER Join (` + totalMsgCountRootCTE + `) as q
  1206  		ON q.channelid=Channels.Id
  1207  		SET TotalMsgCountRoot = q.newcount, LastRootPostAt=q.lastpost;
  1208  	`
  1209  		updateChannelMembers = `
  1210  		UPDATE ChannelMembers CM
  1211  		INNER JOIN (` + channelsCTE + `) as q
  1212  		ON q.id=CM.ChannelId and LastViewedAt >= q.lastrootpostat
  1213  		SET MsgCountRoot=TotalMsgCountRoot
  1214  		`
  1215  	}
  1216  
  1217  	if !totalMsgCountRootExists {
  1218  		if _, err := sqlStore.GetMaster().ExecNoTimeout(updateChannels); err != nil {
  1219  			mlog.Error("Error updating Channels table", mlog.Err(err))
  1220  		}
  1221  	}
  1222  	if !msgCountRootExists {
  1223  		if _, err := sqlStore.GetMaster().ExecNoTimeout(updateChannelMembers); err != nil {
  1224  			mlog.Error("Error updating ChannelMembers table", mlog.Err(err))
  1225  		}
  1226  	}
  1227  }
  1228  
  1229  func hasMissingMigrationsVersion535(sqlStore *SqlStore) bool {
  1230  	if !sqlStore.DoesColumnExist("SidebarCategories", "Collapsed") {
  1231  		return true
  1232  	}
  1233  	if !sqlStore.DoesColumnExist("Reactions", "RemoteId") {
  1234  		return true
  1235  	}
  1236  	if !sqlStore.DoesColumnExist("Users", "RemoteId") {
  1237  		return true
  1238  	}
  1239  	if !sqlStore.DoesColumnExist("Posts", "RemoteId") {
  1240  		return true
  1241  	}
  1242  	if !sqlStore.DoesColumnExist("FileInfo", "RemoteId") {
  1243  		return true
  1244  	}
  1245  	if !sqlStore.DoesColumnExist("UploadSessions", "RemoteId") {
  1246  		return true
  1247  	}
  1248  	if !sqlStore.DoesColumnExist("UploadSessions", "ReqFileId") {
  1249  		return true
  1250  	}
  1251  	if !sqlStore.DoesColumnExist("SharedChannelUsers", "ChannelId") {
  1252  		return true
  1253  	}
  1254  
  1255  	rolesPermissionsInfo, err := sqlStore.GetColumnInfo("Roles", "Permissions")
  1256  	if err != nil {
  1257  		mlog.Error("Error getting column info for migration check",
  1258  			mlog.String("table", "Roles"),
  1259  			mlog.String("column", "Permissions"),
  1260  			mlog.Err(err),
  1261  		)
  1262  		return true
  1263  	}
  1264  
  1265  	if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  1266  		if rolesPermissionsInfo.DataType != "text" {
  1267  			return true
  1268  		}
  1269  	} else if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1270  		if rolesPermissionsInfo.DataType != "longtext" {
  1271  			return true
  1272  		}
  1273  	}
  1274  
  1275  	if !sqlStore.DoesColumnExist("ChannelMembers", "MentionCountRoot") {
  1276  		return true
  1277  	}
  1278  	if !sqlStore.DoesColumnExist("Channels", "TotalMsgCountRoot") {
  1279  		return true
  1280  	}
  1281  	if !sqlStore.DoesColumnExist("ChannelMembers", "MsgCountRoot") {
  1282  		return true
  1283  	}
  1284  
  1285  	// Check if the collapsable threads queries were applied
  1286  	msgRootCount, _, err := sqlStore.getQueryBuilder().Select(`COUNT(*) as countRoot`).
  1287  		From("ChannelMembers").
  1288  		Where("MsgCountRoot is NULL or MentionCountRoot is NULL").
  1289  		ToSql()
  1290  	if err != nil {
  1291  		mlog.Error("Error creating msg count root query", mlog.Err(err))
  1292  		return true
  1293  	}
  1294  	countRoot, err := sqlStore.GetMaster().SelectInt(msgRootCount)
  1295  	if err != nil {
  1296  		mlog.Error("Error fetching msg count root", mlog.Err(err))
  1297  		return true
  1298  	} else if countRoot > 0 {
  1299  		return true
  1300  	}
  1301  
  1302  	return false
  1303  }
  1304  
  1305  func upgradeDatabaseToVersion536(sqlStore *SqlStore) {
  1306  	if hasMissingMigrationsVersion536(sqlStore) {
  1307  		sqlStore.CreateColumnIfNotExists("SharedChannelUsers", "ChannelId", "VARCHAR(26)", "VARCHAR(26)", "")
  1308  		sqlStore.CreateColumnIfNotExists("SharedChannelRemotes", "LastPostUpdateAt", "bigint", "bigint", "0")
  1309  		sqlStore.CreateColumnIfNotExists("SharedChannelRemotes", "LastPostId", "VARCHAR(26)", "VARCHAR(26)", "")
  1310  
  1311  		sqlStore.CreateColumnIfNotExistsNoDefault("Status", "DNDEndTime", "bigint", "bigint")
  1312  		sqlStore.CreateColumnIfNotExistsNoDefault("Status", "PrevStatus", "VARCHAR(32)", "VARCHAR(32)")
  1313  	}
  1314  
  1315  	if shouldPerformUpgrade(sqlStore, Version5350, Version5360) {
  1316  		saveSchemaVersion(sqlStore, Version5360)
  1317  	}
  1318  }
  1319  
  1320  func hasMissingMigrationsVersion536(sqlStore *SqlStore) bool {
  1321  	if !sqlStore.DoesColumnExist("SharedChannelUsers", "ChannelId") {
  1322  		return true
  1323  	}
  1324  	if !sqlStore.DoesColumnExist("SharedChannelRemotes", "LastPostUpdateAt") {
  1325  		return true
  1326  	}
  1327  	if !sqlStore.DoesColumnExist("SharedChannelRemotes", "LastPostId") {
  1328  		return true
  1329  	}
  1330  	if !sqlStore.DoesColumnExist("Status", "DNDEndTime") {
  1331  		return true
  1332  	}
  1333  	if !sqlStore.DoesColumnExist("Status", "PrevStatus") {
  1334  		return true
  1335  	}
  1336  
  1337  	return false
  1338  }
  1339  
  1340  func upgradeDatabaseToVersion537(sqlStore *SqlStore) {
  1341  	if hasMissingMigrationsVersion537(sqlStore) {
  1342  		sqlStore.RemoveIndexIfExists("idx_posts_channel_id", "Posts")
  1343  		sqlStore.RemoveIndexIfExists("idx_channels_name", "Channels")
  1344  		sqlStore.RemoveIndexIfExists("idx_publicchannels_name", "PublicChannels")
  1345  		sqlStore.RemoveIndexIfExists("idx_channelmembers_channel_id", "ChannelMembers")
  1346  		sqlStore.RemoveIndexIfExists("idx_emoji_name", "Emoji")
  1347  		sqlStore.RemoveIndexIfExists("idx_oauthaccessdata_client_id", "OAuthAccessData")
  1348  		sqlStore.RemoveIndexIfExists("idx_oauthauthdata_client_id", "OAuthAuthData")
  1349  		sqlStore.RemoveIndexIfExists("idx_preferences_user_id", "Preferences")
  1350  		sqlStore.RemoveIndexIfExists("idx_notice_views_user_id", "ProductNoticeViewState")
  1351  		sqlStore.RemoveIndexIfExists("idx_notice_views_user_notice", "ProductNoticeViewState")
  1352  		sqlStore.RemoveIndexIfExists("idx_status_user_id", "Status")
  1353  		sqlStore.RemoveIndexIfExists("idx_teammembers_team_id", "TeamMembers")
  1354  		sqlStore.RemoveIndexIfExists("idx_teams_name", "Teams")
  1355  		sqlStore.RemoveIndexIfExists("idx_user_access_tokens_token", "UserAccessTokens")
  1356  		sqlStore.RemoveIndexIfExists("idx_user_terms_of_service_user_id", "UserTermsOfService")
  1357  		sqlStore.RemoveIndexIfExists("idx_users_email", "Users")
  1358  		sqlStore.RemoveIndexIfExists("idx_sharedchannelusers_user_id", "SharedChannelUsers")
  1359  		sqlStore.RemoveIndexIfExists("IDX_RetentionPolicies_DisplayName_Id", "RetentionPolicies")
  1360  		sqlStore.CreateIndexIfNotExists("IDX_RetentionPolicies_DisplayName", "RetentionPolicies", "DisplayName")
  1361  	}
  1362  
  1363  	if shouldPerformUpgrade(sqlStore, Version5360, Version5370) {
  1364  		saveSchemaVersion(sqlStore, Version5370)
  1365  	}
  1366  }
  1367  
  1368  func hasMissingMigrationsVersion537(sqlStore *SqlStore) bool {
  1369  	if sqlStore.DoesIndexExist("idx_posts_create_at", "Posts") {
  1370  		return true
  1371  	}
  1372  	if sqlStore.DoesIndexExist("idx_channels_name", "Channels") {
  1373  		return true
  1374  	}
  1375  	if sqlStore.DoesIndexExist("idx_publicchannels_name", "PublicChannels") {
  1376  		return true
  1377  	}
  1378  	if sqlStore.DoesIndexExist("idx_channelmembers_channel_id", "ChannelMembers") {
  1379  		return true
  1380  	}
  1381  	if sqlStore.DoesIndexExist("idx_emoji_name", "Emoji") {
  1382  		return true
  1383  	}
  1384  	if sqlStore.DoesIndexExist("idx_oauthaccessdata_client_id", "OAuthAccessData") {
  1385  		return true
  1386  	}
  1387  	if sqlStore.DoesIndexExist("idx_oauthauthdata_client_id", "OAuthAuthData") {
  1388  		return true
  1389  	}
  1390  	if sqlStore.DoesIndexExist("idx_preferences_user_id", "Preferences") {
  1391  		return true
  1392  	}
  1393  	if sqlStore.DoesIndexExist("idx_notice_views_user_id", "ProductNoticeViewState") {
  1394  		return true
  1395  	}
  1396  	if sqlStore.DoesIndexExist("idx_notice_views_user_notice", "ProductNoticeViewState") {
  1397  		return true
  1398  	}
  1399  	if sqlStore.DoesIndexExist("idx_status_user_id", "Status") {
  1400  		return true
  1401  	}
  1402  	if sqlStore.DoesIndexExist("idx_teammembers_team_id", "TeamMembers") {
  1403  		return true
  1404  	}
  1405  	if sqlStore.DoesIndexExist("idx_teams_name", "Teams") {
  1406  		return true
  1407  	}
  1408  	if sqlStore.DoesIndexExist("idx_user_access_tokens_token", "UserAccessTokens") {
  1409  		return true
  1410  	}
  1411  	if sqlStore.DoesIndexExist("idx_user_terms_of_service_user_id", "UserTermsOfService") {
  1412  		return true
  1413  	}
  1414  	if sqlStore.DoesIndexExist("idx_users_email", "Users") {
  1415  		return true
  1416  	}
  1417  	if sqlStore.DoesIndexExist("idx_sharedchannelusers_user_id", "SharedChannelUsers") {
  1418  		return true
  1419  	}
  1420  	if sqlStore.DoesIndexExist("IDX_RetentionPolicies_DisplayName_Id", "RetentionPolicies") {
  1421  		return true
  1422  	}
  1423  	if !sqlStore.DoesIndexExist("IDX_RetentionPolicies_DisplayName", "RetentionPolicies") {
  1424  		return true
  1425  	}
  1426  
  1427  	return false
  1428  }
  1429  
  1430  func upgradeDatabaseToVersion538(sqlStore *SqlStore) {
  1431  	if shouldPerformUpgrade(sqlStore, Version5370, Version5380) {
  1432  		fixCRTChannelMembershipCounts(sqlStore)
  1433  		fixCRTThreadCountsAndUnreads(sqlStore)
  1434  
  1435  		saveSchemaVersion(sqlStore, Version5380)
  1436  	}
  1437  }
  1438  
  1439  // fixCRTThreadCountsAndUnreads Marks threads as read for users where the last
  1440  // reply time of the thread is earlier than the time the user viewed the channel.
  1441  // Marking a thread means setting the mention count to zero and setting the
  1442  // last viewed at time of the the thread as the last viewed at time
  1443  // of the channel
  1444  func fixCRTThreadCountsAndUnreads(sqlStore *SqlStore) {
  1445  	var system model.System
  1446  	if err := sqlStore.GetMaster().SelectOne(&system, "SELECT * FROM Systems WHERE Name = 'CRTThreadCountsAndUnreadsMigrationComplete'"); err == nil {
  1447  		return
  1448  	}
  1449  
  1450  	threadMembershipsCTE := `
  1451  		SELECT PostId, UserId, ChannelMembers.LastViewedAt as CM_LastViewedAt, Threads.LastReplyAt
  1452  		FROM Threads
  1453  		INNER JOIN ChannelMembers on ChannelMembers.ChannelId = Threads.ChannelId
  1454  		WHERE Threads.LastReplyAt <= ChannelMembers.LastViewedAt
  1455  	`
  1456  	updateThreadMembershipQuery := `
  1457  		WITH q as (` + threadMembershipsCTE + `)
  1458  		UPDATE ThreadMemberships set LastViewed = q.CM_LastViewedAt + 1, UnreadMentions = 0, LastUpdated = :Now
  1459  		FROM q WHERE ThreadMemberships.Postid = q.PostId AND ThreadMemberships.UserId = q.UserId
  1460  	`
  1461  	if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1462  		updateThreadMembershipQuery = `
  1463  			UPDATE ThreadMemberships
  1464  			INNER JOIN (` + threadMembershipsCTE + `) as q
  1465  			ON ThreadMemberships.Postid = q.PostId AND ThreadMemberships.UserId = q.UserId
  1466  			SET LastViewed = q.CM_LastViewedAt + 1, UnreadMentions = 0, LastUpdated = :Now
  1467  		`
  1468  	}
  1469  
  1470  	if _, err := sqlStore.GetMaster().ExecNoTimeout(updateThreadMembershipQuery, map[string]interface{}{"Now": model.GetMillis()}); err != nil {
  1471  		mlog.Error("Error updating lastviewedat and unreadmentions of threadmemberships", mlog.Err(err))
  1472  		return
  1473  	}
  1474  
  1475  	if _, err := sqlStore.GetMaster().ExecNoTimeout("INSERT INTO Systems VALUES ('CRTThreadCountsAndUnreadsMigrationComplete', 'true')"); err != nil {
  1476  		mlog.Error("Error marking migration as done", mlog.Err(err))
  1477  	}
  1478  }
  1479  
  1480  // fixCRTChannelMembershipCounts fixes the channel counts, i.e. the total message count,
  1481  // total root message count, mention count, and mention count in root messages for users
  1482  // who have viewed the channel after the last post in the channel
  1483  func fixCRTChannelMembershipCounts(sqlStore *SqlStore) {
  1484  	var system model.System
  1485  	if err := sqlStore.GetMaster().SelectOne(&system, "SELECT * FROM Systems WHERE Name = 'CRTChannelMembershipCountsMigrationComplete'"); err == nil {
  1486  		return
  1487  	}
  1488  	channelMembershipsCountsAndMentions := `
  1489  		UPDATE ChannelMembers
  1490  		SET MentionCount=0, MentionCountRoot=0, MsgCount=Channels.TotalMsgCount, MsgCountRoot=Channels.TotalMsgCountRoot, LastUpdateAt = :Now
  1491  		FROM Channels
  1492  		WHERE ChannelMembers.Channelid = Channels.Id AND ChannelMembers.LastViewedAt >= Channels.LastPostAt;
  1493  	`
  1494  
  1495  	if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1496  		channelMembershipsCountsAndMentions = `
  1497  			UPDATE ChannelMembers
  1498  			INNER JOIN Channels on Channels.Id = ChannelMembers.ChannelId
  1499  			SET MentionCount=0, MentionCountRoot=0, MsgCount=Channels.TotalMsgCount, MsgCountRoot=Channels.TotalMsgCountRoot, LastUpdateAt = :Now
  1500  			WHERE ChannelMembers.LastViewedAt >= Channels.LastPostAt;
  1501  		`
  1502  	}
  1503  
  1504  	if _, err := sqlStore.GetMaster().ExecNoTimeout(channelMembershipsCountsAndMentions, map[string]interface{}{"Now": model.GetMillis()}); err != nil {
  1505  		mlog.Error("Error updating counts and unreads for channelmemberships", mlog.Err(err))
  1506  		return
  1507  	}
  1508  	if _, err := sqlStore.GetMaster().ExecNoTimeout("INSERT INTO Systems VALUES ('CRTChannelMembershipCountsMigrationComplete', 'true')"); err != nil {
  1509  		mlog.Error("Error marking migration as done", mlog.Err(err))
  1510  	}
  1511  }
  1512  
  1513  func upgradeDatabaseToVersion539(sqlStore *SqlStore) {
  1514  	if shouldPerformUpgrade(sqlStore, Version5380, Version5390) {
  1515  		saveSchemaVersion(sqlStore, Version5390)
  1516  	}
  1517  }