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