From c3ae3f20f58b25aa6aba480ddc2239fd09e610cb Mon Sep 17 00:00:00 2001 From: Corey Hulen Date: Wed, 24 Aug 2016 16:17:40 -0800 Subject: PLT-3695 refactoring to use sql_upgrader (#3788) * PLT-3695 unitying upgrade support * PLT-3695 refactoring to use sql_upgrader * Fixing unit test * Adding 3.3 to 3.4 * Fixing upgrading * Seperating DB schema from version.go * Fixing upgrade cmd * Moving to const for exit codes * remving old unused code --- config/config.json | 2 +- mattermost.go | 338 +----------------------------------------- store/sql_audit_store.go | 3 - store/sql_channel_store.go | 3 - store/sql_command_store.go | 4 - store/sql_compliance_store.go | 3 - store/sql_emoji_store.go | 3 - store/sql_license_store.go | 3 - store/sql_oauth_store.go | 14 -- store/sql_post_store.go | 3 - store/sql_preference_store.go | 3 - store/sql_recovery_store.go | 3 - store/sql_session_store.go | 8 - store/sql_status_store.go | 3 - store/sql_store.go | 177 ++++++++-------------- store/sql_store_test.go | 28 ---- store/sql_system_store.go | 3 - store/sql_team_store.go | 4 - store/sql_upgrade.go | 190 ++++++++++++++++++++++++ store/sql_user_store.go | 73 --------- store/sql_webhook_store.go | 10 -- 21 files changed, 250 insertions(+), 628 deletions(-) create mode 100644 store/sql_upgrade.go diff --git a/config/config.json b/config/config.json index 8374e695b..56ced04b5 100644 --- a/config/config.json +++ b/config/config.json @@ -220,4 +220,4 @@ "InterNodeListenAddress": ":8075", "InterNodeUrls": [] } -} +} \ No newline at end of file diff --git a/mattermost.go b/mattermost.go index d3007f01b..be824e996 100644 --- a/mattermost.go +++ b/mattermost.go @@ -7,7 +7,6 @@ import ( "bufio" "flag" "fmt" - "html/template" "io/ioutil" "net/http" "net/url" @@ -117,8 +116,6 @@ func main() { *utils.Cfg.ServiceSettings.EnableDeveloper = true } - // Special case for upgrading the db to 3.0 - // ADDED for 3.0 REMOVE for 3.4 cmdUpdateDb30() api.NewServer() @@ -436,346 +433,13 @@ func cmdRunClientTests() { } } -// ADDED for 3.0 REMOVE for 3.4 func cmdUpdateDb30() { if flagCmdUpdateDb30 { - api.Srv = &api.Server{} - api.Srv.Store = store.NewSqlStoreForUpgrade30() - store := api.Srv.Store.(*store.SqlStore) - utils.InitHTML() - - l4g.Info("Attempting to run special upgrade of the database schema to version 3.0 for user model changes") - time.Sleep(time.Second) - - if !store.DoesColumnExist("Users", "TeamId") { - fmt.Println("**WARNING** the database schema appears to be upgraded to 3.0") - flushLogAndExit(1) - } - - if !(store.SchemaVersion == "2.2.0" || - store.SchemaVersion == "2.1.0" || - store.SchemaVersion == "2.0.0") { - fmt.Println("**WARNING** the database schema needs to be version 2.2.0, 2.1.0 or 2.0.0 to upgrade") - flushLogAndExit(1) - } - - fmt.Println("\nPlease see http://www.mattermost.org/upgrade-to-3-0/") - fmt.Println("**WARNING** This upgrade process will be irreversible.") - - if len(flagConfirmBackup) == 0 { - fmt.Print("Have you performed a database backup? (YES/NO): ") - fmt.Scanln(&flagConfirmBackup) - } - - if flagConfirmBackup != "YES" { - fmt.Fprintln(os.Stderr, "ABORTED: You did not answer YES exactly, in all capitals.") - flushLogAndExit(1) - } - - var teams []*TeamForUpgrade - - if _, err := store.GetMaster().Select(&teams, "SELECT Id, Name FROM Teams"); err != nil { - l4g.Error("Failed to load all teams details=%v", err) - flushLogAndExit(1) - } - - if len(flagTeamName) == 0 { - fmt.Println(fmt.Sprintf("We found %v teams.", len(teams))) - - for _, team := range teams { - fmt.Println(team.Name) - } - - fmt.Print("Please pick a primary team from the list above: ") - fmt.Scanln(&flagTeamName) - } - - var team *TeamForUpgrade - for _, t := range teams { - if t.Name == flagTeamName { - team = t - break - } - } - - if team == nil { - l4g.Error("Failed to find primary team details") - flushLogAndExit(1) - } - - l4g.Info("Starting special 3.0 database upgrade with performed_backup=YES team_name=%v", team.Name) - l4g.Info("Primary team %v will be left unchanged", team.Name) - l4g.Info("Upgrading primary team %v", team.Name) - - uniqueEmails := make(map[string]bool) - uniqueUsernames := make(map[string]bool) - uniqueAuths := make(map[string]bool) - primaryUsers := convertTeamTo30(team.Name, team, uniqueEmails, uniqueUsernames, uniqueAuths) - - l4g.Info("Upgraded %v users", len(primaryUsers)) - - for _, otherTeam := range teams { - if otherTeam.Id != team.Id { - l4g.Info("Upgrading team %v", otherTeam.Name) - users := convertTeamTo30(team.Name, otherTeam, uniqueEmails, uniqueUsernames, uniqueAuths) - l4g.Info("Upgraded %v users", len(users)) - - } - } - - l4g.Info("Altering other scheme changes needed 3.0 for user model changes") - - if _, err := store.GetMaster().Exec(` - UPDATE Channels - SET - TeamId = '' - WHERE - Type = 'D' - `, - ); err != nil { - l4g.Error("Failed to update direct channel types details=%v", err) - flushLogAndExit(1) - } - - if _, err := store.GetMaster().Exec(` - UPDATE Users - SET - AuthData = NULL - WHERE - AuthData = '' - `, - ); err != nil { - l4g.Error("Failed to update AuthData types details=%v", err) - flushLogAndExit(1) - } - - extraLength := store.GetMaxLengthOfColumnIfExists("Audits", "ExtraInfo") - if len(extraLength) > 0 && extraLength != "1024" { - store.AlterColumnTypeIfExists("Audits", "ExtraInfo", "VARCHAR(1024)", "VARCHAR(1024)") - } - - actionLength := store.GetMaxLengthOfColumnIfExists("Audits", "Action") - if len(actionLength) > 0 && actionLength != "512" { - store.AlterColumnTypeIfExists("Audits", "Action", "VARCHAR(512)", "VARCHAR(512)") - } - - if store.DoesColumnExist("Sessions", "TeamId") { - store.RemoveColumnIfExists("Sessions", "TeamId") - store.GetMaster().Exec(`TRUNCATE Sessions`) - } - - // ADDED for 2.2 REMOVE for 2.6 - store.CreateColumnIfNotExists("Users", "MfaActive", "tinyint(1)", "boolean", "0") - store.CreateColumnIfNotExists("Users", "MfaSecret", "varchar(128)", "character varying(128)", "") - - // ADDED for 2.2 REMOVE for 2.6 - if store.DoesColumnExist("Users", "TeamId") { - store.RemoveIndexIfExists("idx_users_team_id", "Users") - store.CreateUniqueIndexIfNotExists("idx_users_email_unique", "Users", "Email") - store.CreateUniqueIndexIfNotExists("idx_users_username_unique", "Users", "Username") - store.CreateUniqueIndexIfNotExists("idx_users_authdata_unique", "Users", "AuthData") - store.RemoveColumnIfExists("Teams", "AllowTeamListing") - store.RemoveColumnIfExists("Users", "TeamId") - } - - l4g.Info("Finished running special upgrade of the database schema to version 3.0 for user model changes") - - if result := <-store.System().Update(&model.System{Name: "Version", Value: model.CurrentVersion}); result.Err != nil { - l4g.Error("Failed to update system schema version details=%v", result.Err) - flushLogAndExit(1) - } - - l4g.Info(utils.T("store.sql.upgraded.warn"), model.CurrentVersion) - fmt.Println("**SUCCESS** with upgrade") - + // This command is a no-op for backwards compatibility flushLogAndExit(0) } } -type UserForUpgrade struct { - Id string - Username string - Email string - Roles string - TeamId string - AuthData *string -} - -func convertTeamTo30(primaryTeamName string, team *TeamForUpgrade, uniqueEmails map[string]bool, uniqueUsernames map[string]bool, uniqueAuths map[string]bool) []*UserForUpgrade { - store := api.Srv.Store.(*store.SqlStore) - var users []*UserForUpgrade - if _, err := store.GetMaster().Select(&users, "SELECT Users.Id, Users.Username, Users.Email, Users.Roles, Users.TeamId, Users.AuthData FROM Users WHERE Users.TeamId = :TeamId", map[string]interface{}{"TeamId": team.Id}); err != nil { - l4g.Error("Failed to load profiles for team details=%v", err) - flushLogAndExit(1) - } - - var members []*model.TeamMember - if result := <-api.Srv.Store.Team().GetMembers(team.Id); result.Err != nil { - l4g.Error("Failed to load team membership details=%v", result.Err) - flushLogAndExit(1) - } else { - members = result.Data.([]*model.TeamMember) - } - - for _, user := range users { - shouldUpdateUser := false - shouldUpdateRole := false - previousRole := user.Roles - previousEmail := user.Email - previousUsername := user.Username - - member := &model.TeamMember{ - TeamId: team.Id, - UserId: user.Id, - } - - if model.IsInRole(user.Roles, model.ROLE_TEAM_ADMIN) { - member.Roles = model.ROLE_TEAM_ADMIN - user.Roles = "" - shouldUpdateRole = true - } - - exists := false - for _, member := range members { - if member.UserId == user.Id { - exists = true - break - } - } - - if !exists { - if result := <-api.Srv.Store.Team().SaveMember(member); result.Err != nil { - l4g.Error("Failed to save membership for %v details=%v", user.Email, result.Err) - flushLogAndExit(1) - } - } - - err := api.MoveFile( - "teams/"+team.Id+"/users/"+user.Id+"/profile.png", - "users/"+user.Id+"/profile.png", - ) - - if err != nil { - l4g.Warn("No profile image to move for %v", user.Email) - } - - if uniqueEmails[user.Email] { - shouldUpdateUser = true - emailParts := strings.Split(user.Email, "@") - if len(emailParts) == 2 { - user.Email = emailParts[0] + "+" + team.Name + "@" + emailParts[1] - } else { - user.Email = user.Email + "." + team.Name - } - - if len(user.Email) > 127 { - user.Email = user.Email[:127] - } - } - - if uniqueUsernames[user.Username] { - shouldUpdateUser = true - user.Username = team.Name + "." + user.Username - - if len(user.Username) > 63 { - user.Username = user.Username[:63] - } - } - - if user.AuthData != nil && *user.AuthData != "" && uniqueAuths[*user.AuthData] { - shouldUpdateUser = true - } - - if shouldUpdateUser { - if _, err := store.GetMaster().Exec(` - UPDATE Users - SET - Email = :Email, - Username = :Username, - Roles = :Roles, - AuthService = '', - AuthData = NULL - WHERE - Id = :Id - `, - map[string]interface{}{ - "Email": user.Email, - "Username": user.Username, - "Roles": user.Roles, - "Id": user.Id, - }, - ); err != nil { - l4g.Error("Failed to update user %v details=%v", user.Email, err) - flushLogAndExit(1) - } - - l4g.Info("modified user_id=%v, changed email from=%v to=%v, changed username from=%v to %v changed roles from=%v to=%v", user.Id, previousEmail, user.Email, previousUsername, user.Username, previousRole, user.Roles) - - emailChanged := previousEmail != user.Email - usernameChanged := previousUsername != user.Username - - if emailChanged || usernameChanged { - bodyPage := utils.NewHTMLTemplate("upgrade_30_body", "") - - EmailChanged := "" - UsernameChanged := "" - - if emailChanged { - EmailChanged = "true" - } - - if usernameChanged { - UsernameChanged = "true" - } - - bodyPage.Html["Info"] = template.HTML(utils.T("api.templates.upgrade_30_body.info", - map[string]interface{}{ - "SiteName": utils.ClientCfg["SiteName"], - "TeamName": team.Name, - "Email": user.Email, - "Username": user.Username, - "EmailChanged": EmailChanged, - "UsernameChanged": UsernameChanged, - })) - - utils.SendMail( - previousEmail, - utils.T("api.templates.upgrade_30_subject.info"), - bodyPage.Render(), - ) - } - } - - if shouldUpdateRole { - if _, err := store.GetMaster().Exec(` - UPDATE Users - SET - Roles = '' - WHERE - Id = :Id - `, - map[string]interface{}{ - "Id": user.Id, - }, - ); err != nil { - l4g.Error("Failed to update user role %v details=%v", user.Email, err) - flushLogAndExit(1) - } - - l4g.Info("modified user_id=%v, changed roles from=%v to=%v", user.Id, previousRole, user.Roles) - } - - uniqueEmails[user.Email] = true - uniqueUsernames[user.Username] = true - - if user.AuthData != nil && *user.AuthData != "" { - uniqueAuths[*user.AuthData] = true - } - } - - return users -} - func cmdCreateTeam() { if flagCmdCreateTeam { if len(flagTeamName) == 0 { diff --git a/store/sql_audit_store.go b/store/sql_audit_store.go index 772a549a3..78e875a74 100644 --- a/store/sql_audit_store.go +++ b/store/sql_audit_store.go @@ -27,9 +27,6 @@ func NewSqlAuditStore(sqlStore *SqlStore) AuditStore { return s } -func (s SqlAuditStore) UpgradeSchemaIfNeeded() { -} - func (s SqlAuditStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_audits_user_id", "Audits", "UserId") } diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go index 463bc0678..acf112f50 100644 --- a/store/sql_channel_store.go +++ b/store/sql_channel_store.go @@ -45,9 +45,6 @@ func NewSqlChannelStore(sqlStore *SqlStore) ChannelStore { return s } -func (s SqlChannelStore) UpgradeSchemaIfNeeded() { -} - func (s SqlChannelStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_channels_team_id", "Channels", "TeamId") s.CreateIndexIfNotExists("idx_channels_name", "Channels", "Name") diff --git a/store/sql_command_store.go b/store/sql_command_store.go index 02b3a0cc5..4332f1e93 100644 --- a/store/sql_command_store.go +++ b/store/sql_command_store.go @@ -34,10 +34,6 @@ func NewSqlCommandStore(sqlStore *SqlStore) CommandStore { return s } -func (s SqlCommandStore) UpgradeSchemaIfNeeded() { - s.CreateColumnIfNotExists("Commands", "Description", "varchar(128)", "varchar(128)", "") -} - func (s SqlCommandStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_command_team_id", "Commands", "TeamId") } diff --git a/store/sql_compliance_store.go b/store/sql_compliance_store.go index 57872aef4..248d5c47b 100644 --- a/store/sql_compliance_store.go +++ b/store/sql_compliance_store.go @@ -30,9 +30,6 @@ func NewSqlComplianceStore(sqlStore *SqlStore) ComplianceStore { return s } -func (s SqlComplianceStore) UpgradeSchemaIfNeeded() { -} - func (s SqlComplianceStore) CreateIndexesIfNotExists() { } diff --git a/store/sql_emoji_store.go b/store/sql_emoji_store.go index 99434ee64..45af85931 100644 --- a/store/sql_emoji_store.go +++ b/store/sql_emoji_store.go @@ -26,9 +26,6 @@ func NewSqlEmojiStore(sqlStore *SqlStore) EmojiStore { return s } -func (es SqlEmojiStore) UpgradeSchemaIfNeeded() { -} - func (es SqlEmojiStore) CreateIndexesIfNotExists() { } diff --git a/store/sql_license_store.go b/store/sql_license_store.go index f5d67bc5d..73faad8b9 100644 --- a/store/sql_license_store.go +++ b/store/sql_license_store.go @@ -23,9 +23,6 @@ func NewSqlLicenseStore(sqlStore *SqlStore) LicenseStore { return ls } -func (ls SqlLicenseStore) UpgradeSchemaIfNeeded() { -} - func (ls SqlLicenseStore) CreateIndexesIfNotExists() { } diff --git a/store/sql_oauth_store.go b/store/sql_oauth_store.go index 0ee9f1ad1..4a15d4f80 100644 --- a/store/sql_oauth_store.go +++ b/store/sql_oauth_store.go @@ -47,20 +47,6 @@ func NewSqlOAuthStore(sqlStore *SqlStore) OAuthStore { return as } -func (as SqlOAuthStore) UpgradeSchemaIfNeeded() { - as.CreateColumnIfNotExists("OAuthApps", "IsTrusted", "tinyint(1)", "boolean", "0") - as.CreateColumnIfNotExists("OAuthApps", "IconURL", "varchar(512)", "varchar(512)", "") - as.CreateColumnIfNotExists("OAuthAccessData", "ClientId", "varchar(26)", "varchar(26)", "") - as.CreateColumnIfNotExists("OAuthAccessData", "UserId", "varchar(26)", "varchar(26)", "") - as.CreateColumnIfNotExists("OAuthAccessData", "ExpiresAt", "bigint", "bigint", "0") - - // ADDED for 3.3 REMOVE for 3.7 - if as.DoesColumnExist("OAuthAccessData", "AuthCode") { - as.RemoveIndexIfExists("idx_oauthaccessdata_auth_code", "OAuthAccessData") - as.RemoveColumnIfExists("OAuthAccessData", "AuthCode") - } -} - func (as SqlOAuthStore) CreateIndexesIfNotExists() { as.CreateIndexIfNotExists("idx_oauthapps_creator_id", "OAuthApps", "CreatorId") as.CreateIndexIfNotExists("idx_oauthaccessdata_client_id", "OAuthAccessData", "ClientId") diff --git a/store/sql_post_store.go b/store/sql_post_store.go index b844bfbca..629308316 100644 --- a/store/sql_post_store.go +++ b/store/sql_post_store.go @@ -37,9 +37,6 @@ func NewSqlPostStore(sqlStore *SqlStore) PostStore { return s } -func (s SqlPostStore) UpgradeSchemaIfNeeded() { -} - func (s SqlPostStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_posts_update_at", "Posts", "UpdateAt") s.CreateIndexIfNotExists("idx_posts_create_at", "Posts", "CreateAt") diff --git a/store/sql_preference_store.go b/store/sql_preference_store.go index a701c3cb8..f6a3b64dc 100644 --- a/store/sql_preference_store.go +++ b/store/sql_preference_store.go @@ -32,9 +32,6 @@ func NewSqlPreferenceStore(sqlStore *SqlStore) PreferenceStore { return s } -func (s SqlPreferenceStore) UpgradeSchemaIfNeeded() { -} - func (s SqlPreferenceStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_preferences_user_id", "Preferences", "UserId") s.CreateIndexIfNotExists("idx_preferences_category", "Preferences", "Category") diff --git a/store/sql_recovery_store.go b/store/sql_recovery_store.go index 17a444ebb..80c86c67c 100644 --- a/store/sql_recovery_store.go +++ b/store/sql_recovery_store.go @@ -23,9 +23,6 @@ func NewSqlPasswordRecoveryStore(sqlStore *SqlStore) PasswordRecoveryStore { return s } -func (s SqlPasswordRecoveryStore) UpgradeSchemaIfNeeded() { -} - func (s SqlPasswordRecoveryStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_password_recovery_code", "PasswordRecovery", "Code") } diff --git a/store/sql_session_store.go b/store/sql_session_store.go index 94694267c..4ddc06302 100644 --- a/store/sql_session_store.go +++ b/store/sql_session_store.go @@ -29,14 +29,6 @@ func NewSqlSessionStore(sqlStore *SqlStore) SessionStore { return us } -func (me SqlSessionStore) UpgradeSchemaIfNeeded() { - // ADDED for 2.1 REMOVE for 2.5 - deviceIdLength := me.GetMaxLengthOfColumnIfExists("Sessions", "DeviceId") - if len(deviceIdLength) > 0 && deviceIdLength != "512" { - me.AlterColumnTypeIfExists("Sessions", "DeviceId", "VARCHAR(512)", "VARCHAR(512)") - } -} - func (me SqlSessionStore) CreateIndexesIfNotExists() { me.CreateIndexIfNotExists("idx_sessions_user_id", "Sessions", "UserId") me.CreateIndexIfNotExists("idx_sessions_token", "Sessions", "Token") diff --git a/store/sql_status_store.go b/store/sql_status_store.go index bb3c7c364..f5259c212 100644 --- a/store/sql_status_store.go +++ b/store/sql_status_store.go @@ -28,9 +28,6 @@ func NewSqlStatusStore(sqlStore *SqlStore) StatusStore { return s } -func (s SqlStatusStore) UpgradeSchemaIfNeeded() { -} - func (s SqlStatusStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_status_user_id", "Status", "UserId") s.CreateIndexIfNotExists("idx_status_status", "Status", "Status") diff --git a/store/sql_store.go b/store/sql_store.go index 2047ad150..4185bb705 100644 --- a/store/sql_store.go +++ b/store/sql_store.go @@ -35,6 +35,33 @@ const ( INDEX_TYPE_DEFAULT = "default" ) +const ( + EXIT_CREATE_TABLE = 100 + EXIT_DB_OPEN = 101 + EXIT_PING = 102 + EXIT_NO_DRIVER = 103 + EXIT_TABLE_EXISTS = 104 + EXIT_TABLE_EXISTS_MYSQL = 105 + EXIT_COLUMN_EXISTS = 106 + EXIT_DOES_COLUMN_EXISTS_POSTGRES = 107 + EXIT_DOES_COLUMN_EXISTS_MYSQL = 108 + EXIT_DOES_COLUMN_EXISTS_MISSING = 109 + EXIT_CREATE_COLUMN_POSTGRES = 110 + EXIT_CREATE_COLUMN_MYSQL = 111 + EXIT_CREATE_COLUMN_MISSING = 112 + EXIT_REMOVE_COLUMN = 113 + EXIT_RENAME_COLUMN = 114 + EXIT_MAX_COLUMN = 115 + EXIT_ALTER_COLUMN = 116 + EXIT_CREATE_INDEX_POSTGRES = 117 + EXIT_CREATE_INDEX_MYSQL = 118 + EXIT_CREATE_INDEX_FULL_MYSQL = 119 + EXIT_CREATE_INDEX_MISSING = 120 + EXIT_REMOVE_INDEX_POSTGRES = 121 + EXIT_REMOVE_INDEX_MYSQL = 122 + EXIT_REMOVE_INDEX_MISSING = 123 +) + type SqlStore struct { master *gorp.DbMap replicas []*gorp.DbMap @@ -86,35 +113,6 @@ func NewSqlStore() Store { sqlStore := initConnection() - // If the version is already set then we are potentially in an 'upgrade needed' state - if sqlStore.SchemaVersion != "" { - // Check to see if it's the most current database schema version - if !model.IsCurrentVersion(sqlStore.SchemaVersion) { - // If we are upgrading from the previous version then print a warning and continue - if model.IsPreviousVersionsSupported(sqlStore.SchemaVersion) { - l4g.Warn(utils.T("store.sql.schema_out_of_date.warn"), sqlStore.SchemaVersion) - l4g.Warn(utils.T("store.sql.schema_upgrade_attempt.warn"), model.CurrentVersion) - } else { - // If this is an 'upgrade needed' state but the user is attempting to skip a version then halt the world - l4g.Critical(utils.T("store.sql.schema_version.critical"), sqlStore.SchemaVersion) - time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.schema_version.critical"), sqlStore.SchemaVersion)) - } - } - } - - // This is a special case for upgrading the schema to the 3.0 user model - // ADDED for 3.0 REMOVE for 3.4 - if sqlStore.SchemaVersion == "2.2.0" || - sqlStore.SchemaVersion == "2.1.0" || - sqlStore.SchemaVersion == "2.0.0" { - l4g.Critical("The database version of %v cannot be automatically upgraded to 3.0 schema", sqlStore.SchemaVersion) - l4g.Critical("You will need to run the command line tool './platform -upgrade_db_30'") - l4g.Critical("Please see 'http://www.mattermost.org/upgrade-to-3-0/' for more information on how to upgrade.") - time.Sleep(time.Second) - os.Exit(1) - } - sqlStore.team = NewSqlTeamStore(sqlStore) sqlStore.channel = NewSqlChannelStore(sqlStore) sqlStore.post = NewSqlPostStore(sqlStore) @@ -136,25 +134,10 @@ func NewSqlStore() Store { if err != nil { l4g.Critical(utils.T("store.sql.creating_tables.critical"), err) time.Sleep(time.Second) - os.Exit(1) - } - - sqlStore.team.(*SqlTeamStore).UpgradeSchemaIfNeeded() - sqlStore.channel.(*SqlChannelStore).UpgradeSchemaIfNeeded() - sqlStore.post.(*SqlPostStore).UpgradeSchemaIfNeeded() - sqlStore.user.(*SqlUserStore).UpgradeSchemaIfNeeded() - sqlStore.audit.(*SqlAuditStore).UpgradeSchemaIfNeeded() - sqlStore.compliance.(*SqlComplianceStore).UpgradeSchemaIfNeeded() - sqlStore.session.(*SqlSessionStore).UpgradeSchemaIfNeeded() - sqlStore.oauth.(*SqlOAuthStore).UpgradeSchemaIfNeeded() - sqlStore.system.(*SqlSystemStore).UpgradeSchemaIfNeeded() - sqlStore.webhook.(*SqlWebhookStore).UpgradeSchemaIfNeeded() - sqlStore.command.(*SqlCommandStore).UpgradeSchemaIfNeeded() - sqlStore.preference.(*SqlPreferenceStore).UpgradeSchemaIfNeeded() - sqlStore.license.(*SqlLicenseStore).UpgradeSchemaIfNeeded() - sqlStore.recovery.(*SqlPasswordRecoveryStore).UpgradeSchemaIfNeeded() - sqlStore.emoji.(*SqlEmojiStore).UpgradeSchemaIfNeeded() - sqlStore.status.(*SqlStatusStore).UpgradeSchemaIfNeeded() + os.Exit(EXIT_CREATE_TABLE) + } + + UpgradeDatabase(sqlStore) sqlStore.team.(*SqlTeamStore).CreateIndexesIfNotExists() sqlStore.channel.(*SqlChannelStore).CreateIndexesIfNotExists() @@ -175,37 +158,6 @@ func NewSqlStore() Store { sqlStore.preference.(*SqlPreferenceStore).DeleteUnusedFeatures() - if model.IsPreviousVersionsSupported(sqlStore.SchemaVersion) && !model.IsCurrentVersion(sqlStore.SchemaVersion) { - sqlStore.system.Update(&model.System{Name: "Version", Value: model.CurrentVersion}) - sqlStore.SchemaVersion = model.CurrentVersion - l4g.Warn(utils.T("store.sql.upgraded.warn"), model.CurrentVersion) - } - - if sqlStore.SchemaVersion == "" { - sqlStore.system.Save(&model.System{Name: "Version", Value: model.CurrentVersion}) - sqlStore.SchemaVersion = model.CurrentVersion - l4g.Info(utils.T("store.sql.schema_set.info"), model.CurrentVersion) - } - - return sqlStore -} - -// ADDED for 3.0 REMOVE for 3.4 -// This is a special case for upgrading the schema to the 3.0 user model -func NewSqlStoreForUpgrade30() *SqlStore { - sqlStore := initConnection() - - sqlStore.team = NewSqlTeamStore(sqlStore) - sqlStore.user = NewSqlUserStore(sqlStore) - sqlStore.system = NewSqlSystemStore(sqlStore) - - err := sqlStore.master.CreateTablesIfNotExists() - if err != nil { - l4g.Critical(utils.T("store.sql.creating_tables.critical"), err) - time.Sleep(time.Second) - os.Exit(1) - } - return sqlStore } @@ -215,7 +167,7 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle if err != nil { l4g.Critical(utils.T("store.sql.open_conn.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.open_conn.critical"), err.Error())) + os.Exit(EXIT_DB_OPEN) } l4g.Info(utils.T("store.sql.pinging.info"), con_type) @@ -223,7 +175,7 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle if err != nil { l4g.Critical(utils.T("store.sql.ping.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.open_conn.panic"), err.Error())) + os.Exit(EXIT_PING) } db.SetMaxIdleConns(maxIdle) @@ -240,7 +192,7 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle } else { l4g.Critical(utils.T("store.sql.dialect_driver.critical")) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.dialect_driver.panic"), err.Error())) + os.Exit(EXIT_NO_DRIVER) } if trace { @@ -276,7 +228,7 @@ func (ss SqlStore) DoesTableExist(tableName string) bool { if err != nil { l4g.Critical(utils.T("store.sql.table_exists.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.table_exists.critical"), err.Error())) + os.Exit(EXIT_TABLE_EXISTS) } return count > 0 @@ -298,7 +250,7 @@ func (ss SqlStore) DoesTableExist(tableName string) bool { if err != nil { l4g.Critical(utils.T("store.sql.table_exists.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.table_exists.critical"), err.Error())) + os.Exit(EXIT_TABLE_EXISTS_MYSQL) } return count > 0 @@ -306,9 +258,9 @@ func (ss SqlStore) DoesTableExist(tableName string) bool { } else { l4g.Critical(utils.T("store.sql.column_exists_missing_driver.critical")) time.Sleep(time.Second) - panic(utils.T("store.sql.column_exists_missing_driver.critical")) + os.Exit(EXIT_COLUMN_EXISTS) + return false } - } func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool { @@ -330,7 +282,7 @@ func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool { l4g.Critical(utils.T("store.sql.column_exists.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.column_exists.critical"), err.Error())) + os.Exit(EXIT_DOES_COLUMN_EXISTS_POSTGRES) } return count > 0 @@ -353,7 +305,7 @@ func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool { if err != nil { l4g.Critical(utils.T("store.sql.column_exists.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.column_exists.critical"), err.Error())) + os.Exit(EXIT_DOES_COLUMN_EXISTS_MYSQL) } return count > 0 @@ -361,9 +313,9 @@ func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool { } else { l4g.Critical(utils.T("store.sql.column_exists_missing_driver.critical")) time.Sleep(time.Second) - panic(utils.T("store.sql.column_exists_missing_driver.critical")) + os.Exit(EXIT_DOES_COLUMN_EXISTS_MISSING) + return false } - } func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, mySqlColType string, postgresColType string, defaultValue string) bool { @@ -377,7 +329,7 @@ func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, if err != nil { l4g.Critical(utils.T("store.sql.create_column.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.create_column.critical"), err.Error())) + os.Exit(EXIT_CREATE_COLUMN_POSTGRES) } return true @@ -387,7 +339,7 @@ func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, if err != nil { l4g.Critical(utils.T("store.sql.create_column.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.create_column.critical"), err.Error())) + os.Exit(EXIT_CREATE_COLUMN_MYSQL) } return true @@ -395,7 +347,8 @@ func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, } else { l4g.Critical(utils.T("store.sql.create_column_missing_driver.critical")) time.Sleep(time.Second) - panic(utils.T("store.sql.create_column_missing_driver.critical")) + os.Exit(EXIT_CREATE_COLUMN_MISSING) + return false } } @@ -409,7 +362,7 @@ func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) boo if err != nil { l4g.Critical(utils.T("store.sql.drop_column.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.drop_column.critical"), err.Error())) + os.Exit(EXIT_REMOVE_COLUMN) } return true @@ -430,7 +383,7 @@ func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, if err != nil { l4g.Critical(utils.T("store.sql.rename_column.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.rename_column.critical"), err.Error())) + os.Exit(EXIT_RENAME_COLUMN) } return true @@ -452,7 +405,7 @@ func (ss SqlStore) GetMaxLengthOfColumnIfExists(tableName string, columnName str if err != nil { l4g.Critical(utils.T("store.sql.maxlength_column.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.maxlength_column.critical"), err.Error())) + os.Exit(EXIT_MAX_COLUMN) } return result @@ -473,7 +426,7 @@ func (ss SqlStore) AlterColumnTypeIfExists(tableName string, columnName string, if err != nil { l4g.Critical(utils.T("store.sql.alter_column_type.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.alter_column_type.critical"), err.Error())) + os.Exit(EXIT_ALTER_COLUMN) } return true @@ -516,7 +469,7 @@ func (ss SqlStore) createIndexIfNotExists(indexName string, tableName string, co if err != nil { l4g.Critical(utils.T("store.sql.create_index.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.create_index.critical"), err.Error())) + os.Exit(EXIT_CREATE_INDEX_POSTGRES) } } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL { @@ -524,7 +477,7 @@ func (ss SqlStore) createIndexIfNotExists(indexName string, tableName string, co if err != nil { l4g.Critical(utils.T("store.sql.check_index.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.check_index.critical"), err.Error())) + os.Exit(EXIT_CREATE_INDEX_MYSQL) } if count > 0 { @@ -540,12 +493,12 @@ func (ss SqlStore) createIndexIfNotExists(indexName string, tableName string, co if err != nil { l4g.Critical(utils.T("store.sql.create_index.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.create_index.critical"), err.Error())) + os.Exit(EXIT_CREATE_INDEX_FULL_MYSQL) } } else { l4g.Critical(utils.T("store.sql.create_index_missing_driver.critical")) time.Sleep(time.Second) - panic(utils.T("store.sql.create_index_missing_driver.critical")) + os.Exit(EXIT_CREATE_INDEX_MISSING) } } @@ -562,7 +515,7 @@ func (ss SqlStore) RemoveIndexIfExists(indexName string, tableName string) { if err != nil { l4g.Critical(utils.T("store.sql.remove_index.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.remove_index.critical"), err.Error())) + os.Exit(EXIT_REMOVE_INDEX_POSTGRES) } } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL { @@ -570,7 +523,7 @@ func (ss SqlStore) RemoveIndexIfExists(indexName string, tableName string) { if err != nil { l4g.Critical(utils.T("store.sql.check_index.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.check_index.critical"), err.Error())) + os.Exit(EXIT_REMOVE_INDEX_MYSQL) } if count > 0 { @@ -581,12 +534,12 @@ func (ss SqlStore) RemoveIndexIfExists(indexName string, tableName string) { if err != nil { l4g.Critical(utils.T("store.sql.remove_index.critical"), err) time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql.remove_index.critical"), err.Error())) + os.Exit(EXIT_REMOVE_INDEX_MYSQL) } } else { l4g.Critical(utils.T("store.sql.create_index_missing_driver.critical")) time.Sleep(time.Second) - panic(utils.T("store.sql.create_index_missing_driver.critical")) + os.Exit(EXIT_REMOVE_INDEX_MISSING) } } @@ -603,20 +556,6 @@ func IsUniqueConstraintError(err string, indexName []string) bool { return unique && field } -// func (ss SqlStore) GetColumnDataType(tableName, columnName string) string { -// dataType, err := ss.GetMaster().SelectStr("SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS where table_name = :Tablename AND column_name = :Columnname", map[string]interface{}{ -// "Tablename": tableName, -// "Columnname": columnName, -// }) -// if err != nil { -// l4g.Critical(utils.T("store.sql.table_column_type.critical"), columnName, tableName, err.Error()) -// time.Sleep(time.Second) -// panic(fmt.Sprintf(utils.T("store.sql.table_column_type.critical"), columnName, tableName, err.Error())) -// } - -// return dataType -// } - func (ss SqlStore) GetMaster() *gorp.DbMap { return ss.master } diff --git a/store/sql_store_test.go b/store/sql_store_test.go index 721e708b5..d65d591ad 100644 --- a/store/sql_store_test.go +++ b/store/sql_store_test.go @@ -34,34 +34,6 @@ func TestSqlStore1(t *testing.T) { utils.LoadConfig("config.json") } -func TestSqlStore2(t *testing.T) { - defer func() { - if r := recover(); r == nil { - t.Fatal("should have been fatal") - } - }() - - utils.LoadConfig("config.json") - utils.Cfg.SqlSettings.DriverName = "missing" - store = NewSqlStore() - - utils.LoadConfig("config.json") -} - -func TestSqlStore3(t *testing.T) { - defer func() { - if r := recover(); r == nil { - t.Fatal("should have been fatal") - } - }() - - utils.LoadConfig("config.json") - utils.Cfg.SqlSettings.DataSource = "missing" - store = NewSqlStore() - - utils.LoadConfig("config.json") -} - func TestEncrypt(t *testing.T) { m := make(map[string]string) diff --git a/store/sql_system_store.go b/store/sql_system_store.go index a2b4f6396..6ae350720 100644 --- a/store/sql_system_store.go +++ b/store/sql_system_store.go @@ -23,9 +23,6 @@ func NewSqlSystemStore(sqlStore *SqlStore) SystemStore { return s } -func (s SqlSystemStore) UpgradeSchemaIfNeeded() { -} - func (s SqlSystemStore) CreateIndexesIfNotExists() { } diff --git a/store/sql_team_store.go b/store/sql_team_store.go index 002d2a3ea..0544ec76c 100644 --- a/store/sql_team_store.go +++ b/store/sql_team_store.go @@ -40,10 +40,6 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore { return s } -func (s SqlTeamStore) UpgradeSchemaIfNeeded() { - s.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0") -} - func (s SqlTeamStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_teams_name", "Teams", "Name") s.CreateIndexIfNotExists("idx_teams_invite_id", "Teams", "InviteId") diff --git a/store/sql_upgrade.go b/store/sql_upgrade.go new file mode 100644 index 000000000..293d1ce6b --- /dev/null +++ b/store/sql_upgrade.go @@ -0,0 +1,190 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package store + +import ( + "os" + "strings" + "time" + + l4g "github.com/alecthomas/log4go" + + "github.com/mattermost/platform/model" + "github.com/mattermost/platform/utils" +) + +const ( + VERSION_3_4_0 = "3.4.0" + VERSION_3_3_0 = "3.3.0" + VERSION_3_2_0 = "3.2.0" + VERSION_3_1_0 = "3.1.0" + VERSION_3_0_0 = "3.0.0" +) + +const ( + EXIT_VERSION_SAVE_MISSING = 1001 + EXIT_TOO_OLD = 1002 + EXIT_VERSION_SAVE = 1003 + EXIT_THEME_MIGRATION = 1004 +) + +func UpgradeDatabase(sqlStore *SqlStore) { + + UpgradeDatabaseToVersion31(sqlStore) + UpgradeDatabaseToVersion32(sqlStore) + UpgradeDatabaseToVersion33(sqlStore) + UpgradeDatabaseToVersion34(sqlStore) + + // If the SchemaVersion is empty this this is the first time it has ran + // so lets set it to the current version. + if sqlStore.SchemaVersion == "" { + if result := <-sqlStore.system.Save(&model.System{Name: "Version", Value: model.CurrentVersion}); result.Err != nil { + l4g.Critical(result.Err.Error()) + time.Sleep(time.Second) + os.Exit(EXIT_VERSION_SAVE_MISSING) + } + + sqlStore.SchemaVersion = model.CurrentVersion + l4g.Info(utils.T("store.sql.schema_set.info"), model.CurrentVersion) + } + + // If we're not on the current version then it's too old to be upgraded + if sqlStore.SchemaVersion != model.CurrentVersion { + l4g.Critical(utils.T("store.sql.schema_version.critical"), sqlStore.SchemaVersion) + time.Sleep(time.Second) + os.Exit(EXIT_TOO_OLD) + } +} + +func saveSchemaVersion(sqlStore *SqlStore, version string) { + if result := <-sqlStore.system.Update(&model.System{Name: "Version", Value: model.CurrentVersion}); result.Err != nil { + l4g.Critical(result.Err.Error()) + time.Sleep(time.Second) + os.Exit(EXIT_VERSION_SAVE) + } + + sqlStore.SchemaVersion = version + l4g.Info(utils.T("store.sql.upgraded.warn"), version) +} + +func shouldPerformUpgrade(sqlStore *SqlStore, currentSchemaVersion string, expectedSchemaVersion string) bool { + if sqlStore.SchemaVersion == currentSchemaVersion { + l4g.Info(utils.T("store.sql.schema_out_of_date.warn"), currentSchemaVersion) + l4g.Info(utils.T("store.sql.schema_upgrade_attempt.warn"), expectedSchemaVersion) + + return true + } + + return false +} + +func UpgradeDatabaseToVersion31(sqlStore *SqlStore) { + if shouldPerformUpgrade(sqlStore, VERSION_3_0_0, VERSION_3_1_0) { + sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "") + saveSchemaVersion(sqlStore, VERSION_3_1_0) + } +} + +func UpgradeDatabaseToVersion32(sqlStore *SqlStore) { + if shouldPerformUpgrade(sqlStore, VERSION_3_1_0, VERSION_3_2_0) { + sqlStore.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0") + + if sqlStore.DoesColumnExist("Users", "ThemeProps") { + params := map[string]interface{}{ + "Category": model.PREFERENCE_CATEGORY_THEME, + "Name": "", + } + + transaction, err := sqlStore.GetMaster().Begin() + if err != nil { + themeMigrationFailed(err) + } + + // increase size of Value column of Preferences table to match the size of the ThemeProps column + if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES { + if _, err := transaction.Exec("ALTER TABLE Preferences ALTER COLUMN Value TYPE varchar(2000)"); err != nil { + themeMigrationFailed(err) + } + } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL { + if _, err := transaction.Exec("ALTER TABLE Preferences MODIFY Value text"); err != nil { + themeMigrationFailed(err) + } + } + + // copy data across + if _, err := transaction.Exec( + `INSERT INTO + Preferences(UserId, Category, Name, Value) + SELECT + Id, '`+model.PREFERENCE_CATEGORY_THEME+`', '', ThemeProps + FROM + Users + WHERE + Users.ThemeProps != 'null'`, params); err != nil { + themeMigrationFailed(err) + } + + // delete old data + if _, err := transaction.Exec("ALTER TABLE Users DROP COLUMN ThemeProps"); err != nil { + themeMigrationFailed(err) + } + + if err := transaction.Commit(); err != nil { + themeMigrationFailed(err) + } + + // rename solarized_* code themes to solarized-* to match client changes in 3.0 + var data model.Preferences + if _, err := sqlStore.GetMaster().Select(&data, "SELECT * FROM Preferences WHERE Category = '"+model.PREFERENCE_CATEGORY_THEME+"' AND Value LIKE '%solarized_%'"); err == nil { + for i := range data { + data[i].Value = strings.Replace(data[i].Value, "solarized_", "solarized-", -1) + } + + sqlStore.Preference().Save(&data) + } + } + + saveSchemaVersion(sqlStore, VERSION_3_2_0) + } +} + +func themeMigrationFailed(err error) { + l4g.Critical(utils.T("store.sql_user.migrate_theme.critical"), err) + time.Sleep(time.Second) + os.Exit(EXIT_THEME_MIGRATION) +} + +func UpgradeDatabaseToVersion33(sqlStore *SqlStore) { + if shouldPerformUpgrade(sqlStore, VERSION_3_2_0, VERSION_3_3_0) { + + sqlStore.CreateColumnIfNotExists("OAuthApps", "IsTrusted", "tinyint(1)", "boolean", "0") + sqlStore.CreateColumnIfNotExists("OAuthApps", "IconURL", "varchar(512)", "varchar(512)", "") + sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ClientId", "varchar(26)", "varchar(26)", "") + sqlStore.CreateColumnIfNotExists("OAuthAccessData", "UserId", "varchar(26)", "varchar(26)", "") + sqlStore.CreateColumnIfNotExists("OAuthAccessData", "ExpiresAt", "bigint", "bigint", "0") + + if sqlStore.DoesColumnExist("OAuthAccessData", "AuthCode") { + sqlStore.RemoveIndexIfExists("idx_oauthaccessdata_auth_code", "OAuthAccessData") + sqlStore.RemoveColumnIfExists("OAuthAccessData", "AuthCode") + } + + sqlStore.RemoveColumnIfExists("Users", "LastActivityAt") + sqlStore.RemoveColumnIfExists("Users", "LastPingAt") + + sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "TriggerWhen", "tinyint", "integer", "0") + + saveSchemaVersion(sqlStore, VERSION_3_3_0) + } +} + +func UpgradeDatabaseToVersion34(sqlStore *SqlStore) { + // TODO XXX FIXME should be removed before release + //if shouldPerformUpgrade(sqlStore, VERSION_3_3_0, VERSION_3_4_0) { + + // do the actual upgrade + + // TODO XXX FIXME should be removed before release + //saveSchemaVersion(sqlStore, VERSION_3_4_0) + //} +} diff --git a/store/sql_user_store.go b/store/sql_user_store.go index e26183c1e..027dcbd75 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -9,9 +9,7 @@ import ( "fmt" "strconv" "strings" - "time" - l4g "github.com/alecthomas/log4go" "github.com/mattermost/platform/model" "github.com/mattermost/platform/utils" ) @@ -49,77 +47,6 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore { return us } -func (us SqlUserStore) UpgradeSchemaIfNeeded() { - // ADDED for 2.0 REMOVE for 2.4 - us.CreateColumnIfNotExists("Users", "Locale", "varchar(5)", "character varying(5)", model.DEFAULT_LOCALE) - - // ADDED for 3.2 REMOVE for 3.6 - if us.DoesColumnExist("Users", "ThemeProps") { - params := map[string]interface{}{ - "Category": model.PREFERENCE_CATEGORY_THEME, - "Name": "", - } - - transaction, err := us.GetMaster().Begin() - if err != nil { - themeMigrationFailed(err) - } - - // increase size of Value column of Preferences table to match the size of the ThemeProps column - if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES { - if _, err := transaction.Exec("ALTER TABLE Preferences ALTER COLUMN Value TYPE varchar(2000)"); err != nil { - themeMigrationFailed(err) - } - } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL { - if _, err := transaction.Exec("ALTER TABLE Preferences MODIFY Value text"); err != nil { - themeMigrationFailed(err) - } - } - - // copy data across - if _, err := transaction.Exec( - `INSERT INTO - Preferences(UserId, Category, Name, Value) - SELECT - Id, '`+model.PREFERENCE_CATEGORY_THEME+`', '', ThemeProps - FROM - Users - WHERE - Users.ThemeProps != 'null'`, params); err != nil { - themeMigrationFailed(err) - } - - // delete old data - if _, err := transaction.Exec("ALTER TABLE Users DROP COLUMN ThemeProps"); err != nil { - themeMigrationFailed(err) - } - - if err := transaction.Commit(); err != nil { - themeMigrationFailed(err) - } - - // rename solarized_* code themes to solarized-* to match client changes in 3.0 - var data model.Preferences - if _, err := us.GetReplica().Select(&data, "SELECT * FROM Preferences WHERE Category = '"+model.PREFERENCE_CATEGORY_THEME+"' AND Value LIKE '%solarized_%'"); err == nil { - for i := range data { - data[i].Value = strings.Replace(data[i].Value, "solarized_", "solarized-", -1) - } - - us.Preference().Save(&data) - } - } - - // ADDED for 3.3 remove for 3.7 - us.RemoveColumnIfExists("Users", "LastActivityAt") - us.RemoveColumnIfExists("Users", "LastPingAt") -} - -func themeMigrationFailed(err error) { - l4g.Critical(utils.T("store.sql_user.migrate_theme.critical"), err) - time.Sleep(time.Second) - panic(fmt.Sprintf(utils.T("store.sql_user.migrate_theme.critical"), err.Error())) -} - func (us SqlUserStore) CreateIndexesIfNotExists() { us.CreateIndexIfNotExists("idx_users_email", "Users", "Email") } diff --git a/store/sql_webhook_store.go b/store/sql_webhook_store.go index 08b8f9976..a71ac6a88 100644 --- a/store/sql_webhook_store.go +++ b/store/sql_webhook_store.go @@ -40,16 +40,6 @@ func NewSqlWebhookStore(sqlStore *SqlStore) WebhookStore { return s } -func (s SqlWebhookStore) UpgradeSchemaIfNeeded() { - s.CreateColumnIfNotExists("IncomingWebhooks", "DisplayName", "varchar(64)", "varchar(64)", "") - s.CreateColumnIfNotExists("IncomingWebhooks", "Description", "varchar(128)", "varchar(128)", "") - - s.CreateColumnIfNotExists("OutgoingWebhooks", "DisplayName", "varchar(64)", "varchar(64)", "") - s.CreateColumnIfNotExists("OutgoingWebhooks", "Description", "varchar(128)", "varchar(128)", "") - s.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "") - s.CreateColumnIfNotExists("OutgoingWebhooks", "TriggerWhen", "tinyint", "integer", "0") -} - func (s SqlWebhookStore) CreateIndexesIfNotExists() { s.CreateIndexIfNotExists("idx_incoming_webhook_user_id", "IncomingWebhooks", "UserId") s.CreateIndexIfNotExists("idx_incoming_webhook_team_id", "IncomingWebhooks", "TeamId") -- cgit v1.2.3-1-g7c22