diff options
Diffstat (limited to 'store/sql_store.go')
-rw-r--r-- | store/sql_store.go | 172 |
1 files changed, 144 insertions, 28 deletions
diff --git a/store/sql_store.go b/store/sql_store.go index 98c67d668..6dcf2e8cd 100644 --- a/store/sql_store.go +++ b/store/sql_store.go @@ -38,6 +38,9 @@ type SqlStore struct { user UserStore audit AuditStore session SessionStore + oauth OAuthStore + system SystemStore + webhook WebhookStore } func NewSqlStore() Store { @@ -48,11 +51,44 @@ func NewSqlStore() Store { utils.Cfg.SqlSettings.DataSource, utils.Cfg.SqlSettings.MaxIdleConns, utils.Cfg.SqlSettings.MaxOpenConns, utils.Cfg.SqlSettings.Trace) - sqlStore.replicas = make([]*gorp.DbMap, len(utils.Cfg.SqlSettings.DataSourceReplicas)) - for i, replica := range utils.Cfg.SqlSettings.DataSourceReplicas { - sqlStore.replicas[i] = setupConnection(fmt.Sprintf("replica-%v", i), utils.Cfg.SqlSettings.DriverName, replica, + if len(utils.Cfg.SqlSettings.DataSourceReplicas) == 0 { + sqlStore.replicas = make([]*gorp.DbMap, 1) + sqlStore.replicas[0] = setupConnection(fmt.Sprintf("replica-%v", 0), utils.Cfg.SqlSettings.DriverName, utils.Cfg.SqlSettings.DataSource, utils.Cfg.SqlSettings.MaxIdleConns, utils.Cfg.SqlSettings.MaxOpenConns, utils.Cfg.SqlSettings.Trace) + } else { + sqlStore.replicas = make([]*gorp.DbMap, len(utils.Cfg.SqlSettings.DataSourceReplicas)) + for i, replica := range utils.Cfg.SqlSettings.DataSourceReplicas { + sqlStore.replicas[i] = setupConnection(fmt.Sprintf("replica-%v", i), utils.Cfg.SqlSettings.DriverName, replica, + utils.Cfg.SqlSettings.MaxIdleConns, utils.Cfg.SqlSettings.MaxOpenConns, + utils.Cfg.SqlSettings.Trace) + } + } + + schemaVersion := sqlStore.GetCurrentSchemaVersion() + + // If the version is already set then we are potentially in an 'upgrade needed' state + if schemaVersion != "" { + // Check to see if it's the most current database schema version + if !model.IsCurrentVersion(schemaVersion) { + // If we are upgrading from the previous version then print a warning and continue + if model.IsPreviousVersion(schemaVersion) { + l4g.Warn("The database schema version of " + schemaVersion + " appears to be out of date") + l4g.Warn("Attempting to upgrade the database schema version to " + 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("The database schema version of " + schemaVersion + " cannot be upgraded. You must not skip a version.") + time.Sleep(time.Second) + panic("The database schema version of " + schemaVersion + " cannot be upgraded. You must not skip a version.") + } + } + } + + // Temporary upgrade code, remove after 0.8.0 release + if sqlStore.DoesTableExist("Sessions") { + if sqlStore.DoesColumnExist("Sessions", "AltId") { + sqlStore.GetMaster().Exec("DROP TABLE IF EXISTS Sessions") + } } sqlStore.team = NewSqlTeamStore(sqlStore) @@ -61,22 +97,41 @@ func NewSqlStore() Store { sqlStore.user = NewSqlUserStore(sqlStore) sqlStore.audit = NewSqlAuditStore(sqlStore) sqlStore.session = NewSqlSessionStore(sqlStore) + sqlStore.oauth = NewSqlOAuthStore(sqlStore) + sqlStore.system = NewSqlSystemStore(sqlStore) + sqlStore.webhook = NewSqlWebhookStore(sqlStore) sqlStore.master.CreateTablesIfNotExists() + sqlStore.team.(*SqlTeamStore).UpgradeSchemaIfNeeded() + sqlStore.channel.(*SqlChannelStore).UpgradeSchemaIfNeeded() + sqlStore.post.(*SqlPostStore).UpgradeSchemaIfNeeded() + sqlStore.user.(*SqlUserStore).UpgradeSchemaIfNeeded() + sqlStore.audit.(*SqlAuditStore).UpgradeSchemaIfNeeded() + sqlStore.session.(*SqlSessionStore).UpgradeSchemaIfNeeded() + sqlStore.oauth.(*SqlOAuthStore).UpgradeSchemaIfNeeded() + sqlStore.system.(*SqlSystemStore).UpgradeSchemaIfNeeded() + sqlStore.webhook.(*SqlWebhookStore).UpgradeSchemaIfNeeded() + sqlStore.team.(*SqlTeamStore).CreateIndexesIfNotExists() sqlStore.channel.(*SqlChannelStore).CreateIndexesIfNotExists() sqlStore.post.(*SqlPostStore).CreateIndexesIfNotExists() sqlStore.user.(*SqlUserStore).CreateIndexesIfNotExists() sqlStore.audit.(*SqlAuditStore).CreateIndexesIfNotExists() sqlStore.session.(*SqlSessionStore).CreateIndexesIfNotExists() + sqlStore.oauth.(*SqlOAuthStore).CreateIndexesIfNotExists() + sqlStore.system.(*SqlSystemStore).CreateIndexesIfNotExists() + sqlStore.webhook.(*SqlWebhookStore).CreateIndexesIfNotExists() - sqlStore.team.(*SqlTeamStore).UpgradeSchemaIfNeeded() - sqlStore.channel.(*SqlChannelStore).UpgradeSchemaIfNeeded() - sqlStore.post.(*SqlPostStore).UpgradeSchemaIfNeeded() - sqlStore.user.(*SqlUserStore).UpgradeSchemaIfNeeded() - sqlStore.audit.(*SqlAuditStore).UpgradeSchemaIfNeeded() - sqlStore.session.(*SqlSessionStore).UpgradeSchemaIfNeeded() + if model.IsPreviousVersion(schemaVersion) { + sqlStore.system.Update(&model.System{Name: "Version", Value: model.CurrentVersion}) + l4g.Warn("The database schema has been upgraded to version " + model.CurrentVersion) + } + + if schemaVersion == "" { + sqlStore.system.Save(&model.System{Name: "Version", Value: model.CurrentVersion}) + l4g.Info("The database schema has been set to version " + model.CurrentVersion) + } return sqlStore } @@ -85,12 +140,12 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle db, err := dbsql.Open(driver, dataSource) if err != nil { - l4g.Critical("Failed to open sql connection to '%v' err:%v", dataSource, err) + l4g.Critical("Failed to open sql connection to err:%v", err) time.Sleep(time.Second) panic("Failed to open sql connection" + err.Error()) } - l4g.Info("Pinging sql %v database at '%v'", con_type, dataSource) + l4g.Info("Pinging sql %v database", con_type) err = db.Ping() if err != nil { l4g.Critical("Failed to ping db err:%v", err) @@ -122,6 +177,56 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle return dbmap } +func (ss SqlStore) GetCurrentSchemaVersion() string { + version, _ := ss.GetMaster().SelectStr("SELECT Value FROM Systems WHERE Name='Version'") + return version +} + +func (ss SqlStore) DoesTableExist(tableName string) bool { + if utils.Cfg.SqlSettings.DriverName == "postgres" { + count, err := ss.GetMaster().SelectInt( + `SELECT count(relname) FROM pg_class WHERE relname=$1`, + strings.ToLower(tableName), + ) + + if err != nil { + l4g.Critical("Failed to check if table exists %v", err) + time.Sleep(time.Second) + panic("Failed to check if table exists " + err.Error()) + } + + return count > 0 + + } else if utils.Cfg.SqlSettings.DriverName == "mysql" { + + count, err := ss.GetMaster().SelectInt( + `SELECT + COUNT(0) AS table_exists + FROM + information_schema.TABLES + WHERE + TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = ? + `, + tableName, + ) + + if err != nil { + l4g.Critical("Failed to check if table exists %v", err) + time.Sleep(time.Second) + panic("Failed to check if table exists " + err.Error()) + } + + return count > 0 + + } else { + l4g.Critical("Failed to check if column exists because of missing driver") + time.Sleep(time.Second) + panic("Failed to check if column exists because of missing driver") + } + +} + func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool { if utils.Cfg.SqlSettings.DriverName == "postgres" { count, err := ss.GetMaster().SelectInt( @@ -135,6 +240,10 @@ func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool { ) if err != nil { + if err.Error() == "pq: relation \""+strings.ToLower(tableName)+"\" does not exist" { + return false + } + l4g.Critical("Failed to check if column exists %v", err) time.Sleep(time.Second) panic("Failed to check if column exists " + err.Error()) @@ -206,26 +315,21 @@ func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, } } -// func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool { +func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool { -// // XXX TODO FIXME this should be removed after 0.6.0 -// if utils.Cfg.SqlSettings.DriverName == "postgres" { -// return false -// } - -// if !ss.DoesColumnExist(tableName, columnName) { -// return false -// } + if !ss.DoesColumnExist(tableName, columnName) { + return false + } -// _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName) -// if err != nil { -// l4g.Critical("Failed to drop column %v", err) -// time.Sleep(time.Second) -// panic("Failed to drop column " + err.Error()) -// } + _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName) + if err != nil { + l4g.Critical("Failed to drop column %v", err) + time.Sleep(time.Second) + panic("Failed to drop column " + err.Error()) + } -// return true -// } + return true +} // func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool { @@ -363,6 +467,18 @@ func (ss SqlStore) Audit() AuditStore { return ss.audit } +func (ss SqlStore) OAuth() OAuthStore { + return ss.oauth +} + +func (ss SqlStore) System() SystemStore { + return ss.system +} + +func (ss SqlStore) Webhook() WebhookStore { + return ss.webhook +} + type mattermConverter struct{} func (me mattermConverter) ToDb(val interface{}) (interface{}, error) { |