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 = ¤tModelVersion 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 }