github.com/dschalla/mattermost-server@v4.8.1-rc1+incompatible/store/sqlstore/upgrade.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package sqlstore
     5  
     6  import (
     7  	"os"
     8  	"strings"
     9  	"time"
    10  
    11  	l4g "github.com/alecthomas/log4go"
    12  
    13  	"github.com/mattermost/mattermost-server/model"
    14  	"github.com/mattermost/mattermost-server/utils"
    15  )
    16  
    17  const (
    18  	VERSION_4_8_1            = "4.8.1"
    19  	VERSION_4_8_0            = "4.8.0"
    20  	VERSION_4_7_2            = "4.7.2"
    21  	VERSION_4_7_1            = "4.7.1"
    22  	VERSION_4_7_0            = "4.7.0"
    23  	VERSION_4_6_0            = "4.6.0"
    24  	VERSION_4_5_0            = "4.5.0"
    25  	VERSION_4_4_0            = "4.4.0"
    26  	VERSION_4_3_0            = "4.3.0"
    27  	VERSION_4_2_0            = "4.2.0"
    28  	VERSION_4_1_0            = "4.1.0"
    29  	VERSION_4_0_0            = "4.0.0"
    30  	VERSION_3_10_0           = "3.10.0"
    31  	VERSION_3_9_0            = "3.9.0"
    32  	VERSION_3_8_0            = "3.8.0"
    33  	VERSION_3_7_0            = "3.7.0"
    34  	VERSION_3_6_0            = "3.6.0"
    35  	VERSION_3_5_0            = "3.5.0"
    36  	VERSION_3_4_0            = "3.4.0"
    37  	VERSION_3_3_0            = "3.3.0"
    38  	VERSION_3_2_0            = "3.2.0"
    39  	VERSION_3_1_0            = "3.1.0"
    40  	VERSION_3_0_0            = "3.0.0"
    41  	OLDEST_SUPPORTED_VERSION = VERSION_3_0_0
    42  )
    43  
    44  const (
    45  	EXIT_VERSION_SAVE_MISSING = 1001
    46  	EXIT_TOO_OLD              = 1002
    47  	EXIT_VERSION_SAVE         = 1003
    48  	EXIT_THEME_MIGRATION      = 1004
    49  )
    50  
    51  func UpgradeDatabase(sqlStore SqlStore) {
    52  
    53  	UpgradeDatabaseToVersion31(sqlStore)
    54  	UpgradeDatabaseToVersion32(sqlStore)
    55  	UpgradeDatabaseToVersion33(sqlStore)
    56  	UpgradeDatabaseToVersion34(sqlStore)
    57  	UpgradeDatabaseToVersion35(sqlStore)
    58  	UpgradeDatabaseToVersion36(sqlStore)
    59  	UpgradeDatabaseToVersion37(sqlStore)
    60  	UpgradeDatabaseToVersion38(sqlStore)
    61  	UpgradeDatabaseToVersion39(sqlStore)
    62  	UpgradeDatabaseToVersion310(sqlStore)
    63  	UpgradeDatabaseToVersion40(sqlStore)
    64  	UpgradeDatabaseToVersion41(sqlStore)
    65  	UpgradeDatabaseToVersion42(sqlStore)
    66  	UpgradeDatabaseToVersion43(sqlStore)
    67  	UpgradeDatabaseToVersion44(sqlStore)
    68  	UpgradeDatabaseToVersion45(sqlStore)
    69  	UpgradeDatabaseToVersion46(sqlStore)
    70  	UpgradeDatabaseToVersion47(sqlStore)
    71  	UpgradeDatabaseToVersion471(sqlStore)
    72  	UpgradeDatabaseToVersion472(sqlStore)
    73  	UpgradeDatabaseToVersion48(sqlStore)
    74  	UpgradeDatabaseToVersion481(sqlStore)
    75  
    76  	// If the SchemaVersion is empty this this is the first time it has ran
    77  	// so lets set it to the current version.
    78  	if sqlStore.GetCurrentSchemaVersion() == "" {
    79  		if result := <-sqlStore.System().SaveOrUpdate(&model.System{Name: "Version", Value: model.CurrentVersion}); result.Err != nil {
    80  			l4g.Critical(result.Err.Error())
    81  			time.Sleep(time.Second)
    82  			os.Exit(EXIT_VERSION_SAVE_MISSING)
    83  		}
    84  
    85  		l4g.Info(utils.T("store.sql.schema_set.info"), model.CurrentVersion)
    86  	}
    87  
    88  	// If we're not on the current version then it's too old to be upgraded
    89  	if sqlStore.GetCurrentSchemaVersion() != model.CurrentVersion {
    90  		l4g.Critical(utils.T("store.sql.schema_version.critical"), sqlStore.GetCurrentSchemaVersion(), OLDEST_SUPPORTED_VERSION, model.CurrentVersion, OLDEST_SUPPORTED_VERSION)
    91  		time.Sleep(time.Second)
    92  		os.Exit(EXIT_TOO_OLD)
    93  	}
    94  }
    95  
    96  func saveSchemaVersion(sqlStore SqlStore, version string) {
    97  	if result := <-sqlStore.System().Update(&model.System{Name: "Version", Value: version}); result.Err != nil {
    98  		l4g.Critical(result.Err.Error())
    99  		time.Sleep(time.Second)
   100  		os.Exit(EXIT_VERSION_SAVE)
   101  	}
   102  
   103  	l4g.Warn(utils.T("store.sql.upgraded.warn"), version)
   104  }
   105  
   106  func shouldPerformUpgrade(sqlStore SqlStore, currentSchemaVersion string, expectedSchemaVersion string) bool {
   107  	if sqlStore.GetCurrentSchemaVersion() == currentSchemaVersion {
   108  		l4g.Warn(utils.T("store.sql.schema_out_of_date.warn"), currentSchemaVersion)
   109  		l4g.Warn(utils.T("store.sql.schema_upgrade_attempt.warn"), expectedSchemaVersion)
   110  
   111  		return true
   112  	}
   113  
   114  	return false
   115  }
   116  
   117  func UpgradeDatabaseToVersion31(sqlStore SqlStore) {
   118  	if shouldPerformUpgrade(sqlStore, VERSION_3_0_0, VERSION_3_1_0) {
   119  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "")
   120  		saveSchemaVersion(sqlStore, VERSION_3_1_0)
   121  	}
   122  }
   123  
   124  func UpgradeDatabaseToVersion32(sqlStore SqlStore) {
   125  	if shouldPerformUpgrade(sqlStore, VERSION_3_1_0, VERSION_3_2_0) {
   126  		sqlStore.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0")
   127  
   128  		saveSchemaVersion(sqlStore, VERSION_3_2_0)
   129  	}
   130  }
   131  
   132  func themeMigrationFailed(err error) {
   133  	l4g.Critical(utils.T("store.sql_user.migrate_theme.critical"), err)
   134  	time.Sleep(time.Second)
   135  	os.Exit(EXIT_THEME_MIGRATION)
   136  }
   137  
   138  func UpgradeDatabaseToVersion33(sqlStore SqlStore) {
   139  	if shouldPerformUpgrade(sqlStore, VERSION_3_2_0, VERSION_3_3_0) {
   140  		if sqlStore.DoesColumnExist("Users", "ThemeProps") {
   141  			params := map[string]interface{}{
   142  				"Category": model.PREFERENCE_CATEGORY_THEME,
   143  				"Name":     "",
   144  			}
   145  
   146  			transaction, err := sqlStore.GetMaster().Begin()
   147  			if err != nil {
   148  				themeMigrationFailed(err)
   149  			}
   150  
   151  			// increase size of Value column of Preferences table to match the size of the ThemeProps column
   152  			if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   153  				if _, err := transaction.Exec("ALTER TABLE Preferences ALTER COLUMN Value TYPE varchar(2000)"); err != nil {
   154  					themeMigrationFailed(err)
   155  				}
   156  			} else if sqlStore.DriverName() == model.DATABASE_DRIVER_MYSQL {
   157  				if _, err := transaction.Exec("ALTER TABLE Preferences MODIFY Value text"); err != nil {
   158  					themeMigrationFailed(err)
   159  				}
   160  			}
   161  
   162  			// copy data across
   163  			if _, err := transaction.Exec(
   164  				`INSERT INTO
   165  					Preferences(UserId, Category, Name, Value)
   166  				SELECT
   167  					Id, '`+model.PREFERENCE_CATEGORY_THEME+`', '', ThemeProps
   168  				FROM
   169  					Users
   170  				WHERE
   171  					Users.ThemeProps != 'null'`, params); err != nil {
   172  				themeMigrationFailed(err)
   173  			}
   174  
   175  			// delete old data
   176  			if _, err := transaction.Exec("ALTER TABLE Users DROP COLUMN ThemeProps"); err != nil {
   177  				themeMigrationFailed(err)
   178  			}
   179  
   180  			if err := transaction.Commit(); err != nil {
   181  				themeMigrationFailed(err)
   182  			}
   183  
   184  			// rename solarized_* code themes to solarized-* to match client changes in 3.0
   185  			var data model.Preferences
   186  			if _, err := sqlStore.GetMaster().Select(&data, "SELECT * FROM Preferences WHERE Category = '"+model.PREFERENCE_CATEGORY_THEME+"' AND Value LIKE '%solarized_%'"); err == nil {
   187  				for i := range data {
   188  					data[i].Value = strings.Replace(data[i].Value, "solarized_", "solarized-", -1)
   189  				}
   190  
   191  				sqlStore.Preference().Save(&data)
   192  			}
   193  		}
   194  
   195  		sqlStore.CreateColumnIfNotExists("OAuthApps", "IsTrusted", "tinyint(1)", "boolean", "0")
   196  		sqlStore.CreateColumnIfNotExists("OAuthApps", "IconURL", "varchar(512)", "varchar(512)", "")
   197  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ClientId", "varchar(26)", "varchar(26)", "")
   198  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "UserId", "varchar(26)", "varchar(26)", "")
   199  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ExpiresAt", "bigint", "bigint", "0")
   200  
   201  		if sqlStore.DoesColumnExist("OAuthAccessData", "AuthCode") {
   202  			sqlStore.RemoveIndexIfExists("idx_oauthaccessdata_auth_code", "OAuthAccessData")
   203  			sqlStore.RemoveColumnIfExists("OAuthAccessData", "AuthCode")
   204  		}
   205  
   206  		sqlStore.RemoveColumnIfExists("Users", "LastActivityAt")
   207  		sqlStore.RemoveColumnIfExists("Users", "LastPingAt")
   208  
   209  		sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "TriggerWhen", "tinyint", "integer", "0")
   210  
   211  		saveSchemaVersion(sqlStore, VERSION_3_3_0)
   212  	}
   213  }
   214  
   215  func UpgradeDatabaseToVersion34(sqlStore SqlStore) {
   216  	if shouldPerformUpgrade(sqlStore, VERSION_3_3_0, VERSION_3_4_0) {
   217  		sqlStore.CreateColumnIfNotExists("Status", "Manual", "BOOLEAN", "BOOLEAN", "0")
   218  		sqlStore.CreateColumnIfNotExists("Status", "ActiveChannel", "varchar(26)", "varchar(26)", "")
   219  
   220  		saveSchemaVersion(sqlStore, VERSION_3_4_0)
   221  	}
   222  }
   223  
   224  func UpgradeDatabaseToVersion35(sqlStore SqlStore) {
   225  	if shouldPerformUpgrade(sqlStore, VERSION_3_4_0, VERSION_3_5_0) {
   226  		sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user' WHERE Roles = ''")
   227  		sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user system_admin' WHERE Roles = 'system_admin'")
   228  		sqlStore.GetMaster().Exec("UPDATE TeamMembers SET Roles = 'team_user' WHERE Roles = ''")
   229  		sqlStore.GetMaster().Exec("UPDATE TeamMembers SET Roles = 'team_user team_admin' WHERE Roles = 'admin'")
   230  		sqlStore.GetMaster().Exec("UPDATE ChannelMembers SET Roles = 'channel_user' WHERE Roles = ''")
   231  		sqlStore.GetMaster().Exec("UPDATE ChannelMembers SET Roles = 'channel_user channel_admin' WHERE Roles = 'admin'")
   232  
   233  		// The rest of the migration from Filenames -> FileIds is done lazily in api.GetFileInfosForPost
   234  		sqlStore.CreateColumnIfNotExists("Posts", "FileIds", "varchar(150)", "varchar(150)", "[]")
   235  
   236  		// Increase maximum length of the Channel table Purpose column.
   237  		if sqlStore.GetMaxLengthOfColumnIfExists("Channels", "Purpose") != "250" {
   238  			sqlStore.AlterColumnTypeIfExists("Channels", "Purpose", "varchar(250)", "varchar(250)")
   239  		}
   240  
   241  		sqlStore.Session().RemoveAllSessions()
   242  
   243  		saveSchemaVersion(sqlStore, VERSION_3_5_0)
   244  	}
   245  }
   246  
   247  func UpgradeDatabaseToVersion36(sqlStore SqlStore) {
   248  	if shouldPerformUpgrade(sqlStore, VERSION_3_5_0, VERSION_3_6_0) {
   249  		sqlStore.CreateColumnIfNotExists("Posts", "HasReactions", "tinyint", "boolean", "0")
   250  
   251  		// Create Team Description column
   252  		sqlStore.CreateColumnIfNotExists("Teams", "Description", "varchar(255)", "varchar(255)", "")
   253  
   254  		// Add a Position column to users.
   255  		sqlStore.CreateColumnIfNotExists("Users", "Position", "varchar(64)", "varchar(64)", "")
   256  
   257  		// Remove ActiveChannel column from Status
   258  		sqlStore.RemoveColumnIfExists("Status", "ActiveChannel")
   259  
   260  		saveSchemaVersion(sqlStore, VERSION_3_6_0)
   261  	}
   262  }
   263  
   264  func UpgradeDatabaseToVersion37(sqlStore SqlStore) {
   265  	if shouldPerformUpgrade(sqlStore, VERSION_3_6_0, VERSION_3_7_0) {
   266  		// Add EditAt column to Posts
   267  		sqlStore.CreateColumnIfNotExists("Posts", "EditAt", " bigint", " bigint", "0")
   268  
   269  		saveSchemaVersion(sqlStore, VERSION_3_7_0)
   270  	}
   271  }
   272  
   273  func UpgradeDatabaseToVersion38(sqlStore SqlStore) {
   274  	if shouldPerformUpgrade(sqlStore, VERSION_3_7_0, VERSION_3_8_0) {
   275  		// Add the IsPinned column to posts.
   276  		sqlStore.CreateColumnIfNotExists("Posts", "IsPinned", "boolean", "boolean", "0")
   277  
   278  		saveSchemaVersion(sqlStore, VERSION_3_8_0)
   279  	}
   280  }
   281  
   282  func UpgradeDatabaseToVersion39(sqlStore SqlStore) {
   283  	if shouldPerformUpgrade(sqlStore, VERSION_3_8_0, VERSION_3_9_0) {
   284  		sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE)
   285  		sqlStore.RemoveTableIfExists("PasswordRecovery")
   286  
   287  		saveSchemaVersion(sqlStore, VERSION_3_9_0)
   288  	}
   289  }
   290  
   291  func UpgradeDatabaseToVersion310(sqlStore SqlStore) {
   292  	if shouldPerformUpgrade(sqlStore, VERSION_3_9_0, VERSION_3_10_0) {
   293  		saveSchemaVersion(sqlStore, VERSION_3_10_0)
   294  	}
   295  }
   296  
   297  func UpgradeDatabaseToVersion40(sqlStore SqlStore) {
   298  	if shouldPerformUpgrade(sqlStore, VERSION_3_10_0, VERSION_4_0_0) {
   299  		saveSchemaVersion(sqlStore, VERSION_4_0_0)
   300  	}
   301  }
   302  
   303  func UpgradeDatabaseToVersion41(sqlStore SqlStore) {
   304  	if shouldPerformUpgrade(sqlStore, VERSION_4_0_0, VERSION_4_1_0) {
   305  		// Increase maximum length of the Users table Roles column.
   306  		if sqlStore.GetMaxLengthOfColumnIfExists("Users", "Roles") != "256" {
   307  			sqlStore.AlterColumnTypeIfExists("Users", "Roles", "varchar(256)", "varchar(256)")
   308  		}
   309  
   310  		sqlStore.RemoveTableIfExists("JobStatuses")
   311  
   312  		saveSchemaVersion(sqlStore, VERSION_4_1_0)
   313  	}
   314  }
   315  
   316  func UpgradeDatabaseToVersion42(sqlStore SqlStore) {
   317  	if shouldPerformUpgrade(sqlStore, VERSION_4_1_0, VERSION_4_2_0) {
   318  		saveSchemaVersion(sqlStore, VERSION_4_2_0)
   319  	}
   320  }
   321  
   322  func UpgradeDatabaseToVersion43(sqlStore SqlStore) {
   323  	if shouldPerformUpgrade(sqlStore, VERSION_4_2_0, VERSION_4_3_0) {
   324  		saveSchemaVersion(sqlStore, VERSION_4_3_0)
   325  	}
   326  }
   327  
   328  func UpgradeDatabaseToVersion44(sqlStore SqlStore) {
   329  	if shouldPerformUpgrade(sqlStore, VERSION_4_3_0, VERSION_4_4_0) {
   330  		// Add the IsActive column to UserAccessToken.
   331  		sqlStore.CreateColumnIfNotExists("UserAccessTokens", "IsActive", "boolean", "boolean", "1")
   332  
   333  		saveSchemaVersion(sqlStore, VERSION_4_4_0)
   334  	}
   335  }
   336  
   337  func UpgradeDatabaseToVersion45(sqlStore SqlStore) {
   338  	if shouldPerformUpgrade(sqlStore, VERSION_4_4_0, VERSION_4_5_0) {
   339  		saveSchemaVersion(sqlStore, VERSION_4_5_0)
   340  	}
   341  }
   342  
   343  func UpgradeDatabaseToVersion46(sqlStore SqlStore) {
   344  	if shouldPerformUpgrade(sqlStore, VERSION_4_5_0, VERSION_4_6_0) {
   345  		sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
   346  		sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "")
   347  		saveSchemaVersion(sqlStore, VERSION_4_6_0)
   348  	}
   349  }
   350  
   351  func UpgradeDatabaseToVersion47(sqlStore SqlStore) {
   352  	if shouldPerformUpgrade(sqlStore, VERSION_4_6_0, VERSION_4_7_0) {
   353  		sqlStore.AlterColumnTypeIfExists("Users", "Position", "varchar(128)", "varchar(128)")
   354  		sqlStore.AlterColumnTypeIfExists("OAuthAuthData", "State", "varchar(1024)", "varchar(1024)")
   355  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email")
   356  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Username")
   357  		saveSchemaVersion(sqlStore, VERSION_4_7_0)
   358  	}
   359  }
   360  
   361  // If any new instances started with 4.7, they would have the bad Email column on the
   362  // ChannelMemberHistory table. So for those cases we need to do an upgrade between
   363  // 4.7.0 and 4.7.1
   364  func UpgradeDatabaseToVersion471(sqlStore SqlStore) {
   365  	if shouldPerformUpgrade(sqlStore, VERSION_4_7_0, VERSION_4_7_1) {
   366  		sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email")
   367  		saveSchemaVersion(sqlStore, VERSION_4_7_1)
   368  	}
   369  }
   370  
   371  func UpgradeDatabaseToVersion472(sqlStore SqlStore) {
   372  	if shouldPerformUpgrade(sqlStore, VERSION_4_7_1, VERSION_4_7_2) {
   373  		sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
   374  		saveSchemaVersion(sqlStore, VERSION_4_7_2)
   375  	}
   376  }
   377  
   378  func UpgradeDatabaseToVersion48(sqlStore SqlStore) {
   379  	if shouldPerformUpgrade(sqlStore, VERSION_4_7_2, VERSION_4_8_0) {
   380  		saveSchemaVersion(sqlStore, VERSION_4_8_0)
   381  	}
   382  }
   383  
   384  func UpgradeDatabaseToVersion481(sqlStore SqlStore) {
   385  	if shouldPerformUpgrade(sqlStore, VERSION_4_8_0, VERSION_4_8_1) {
   386  		sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
   387  		saveSchemaVersion(sqlStore, VERSION_4_8_1)
   388  	}
   389  }