2015-01-20 21:15:48 +08:00
|
|
|
package migrator
|
2015-01-19 01:41:03 +08:00
|
|
|
|
|
|
|
|
import (
|
2021-05-01 02:06:33 +08:00
|
|
|
"fmt"
|
2015-01-19 01:41:03 +08:00
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
_ "github.com/go-sql-driver/mysql"
|
|
|
|
|
_ "github.com/lib/pq"
|
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
2022-02-16 00:54:27 +08:00
|
|
|
"go.uber.org/atomic"
|
2020-04-01 21:57:21 +08:00
|
|
|
"xorm.io/xorm"
|
2021-11-25 03:56:07 +08:00
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
2015-01-19 01:41:03 +08:00
|
|
|
)
|
|
|
|
|
|
2022-02-16 00:54:27 +08:00
|
|
|
var (
|
|
|
|
|
ErrMigratorIsLocked = fmt.Errorf("migrator is locked")
|
|
|
|
|
ErrMigratorIsUnlocked = fmt.Errorf("migrator is unlocked")
|
|
|
|
|
)
|
|
|
|
|
|
2015-01-19 01:41:03 +08:00
|
|
|
type Migrator struct {
|
2022-06-04 07:59:49 +08:00
|
|
|
DBEngine *xorm.Engine
|
|
|
|
|
Dialect Dialect
|
|
|
|
|
migrations []Migration
|
|
|
|
|
migrationIds map[string]struct{}
|
|
|
|
|
Logger log.Logger
|
|
|
|
|
Cfg *setting.Cfg
|
|
|
|
|
isLocked atomic.Bool
|
2023-04-19 23:34:19 +08:00
|
|
|
logMap map[string]MigrationLog
|
2023-05-23 02:31:07 +08:00
|
|
|
tableName string
|
2015-01-19 01:41:03 +08:00
|
|
|
}
|
|
|
|
|
|
2015-01-20 15:50:08 +08:00
|
|
|
type MigrationLog struct {
|
|
|
|
|
Id int64
|
2020-11-11 13:21:08 +08:00
|
|
|
MigrationID string `xorm:"migration_id"`
|
|
|
|
|
SQL string `xorm:"sql"`
|
2015-01-20 15:50:08 +08:00
|
|
|
Success bool
|
|
|
|
|
Error string
|
|
|
|
|
Timestamp time.Time
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 20:08:39 +08:00
|
|
|
func NewMigrator(engine *xorm.Engine, cfg *setting.Cfg) *Migrator {
|
2023-05-23 02:31:07 +08:00
|
|
|
return NewScopedMigrator(engine, cfg, "")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewScopedMigrator should only be used for the transition to a new storage engine
|
|
|
|
|
func NewScopedMigrator(engine *xorm.Engine, cfg *setting.Cfg, scope string) *Migrator {
|
|
|
|
|
mg := &Migrator{
|
|
|
|
|
Cfg: cfg,
|
|
|
|
|
DBEngine: engine,
|
|
|
|
|
migrations: make([]Migration, 0),
|
|
|
|
|
migrationIds: make(map[string]struct{}),
|
|
|
|
|
Dialect: NewDialect(engine),
|
|
|
|
|
}
|
|
|
|
|
if scope == "" {
|
|
|
|
|
mg.tableName = "migration_log"
|
|
|
|
|
mg.Logger = log.New("migrator")
|
|
|
|
|
} else {
|
|
|
|
|
mg.tableName = scope + "_migration_log"
|
|
|
|
|
mg.Logger = log.New(scope + " migrator")
|
|
|
|
|
}
|
2015-01-19 01:41:03 +08:00
|
|
|
return mg
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-23 02:31:07 +08:00
|
|
|
// AddCreateMigration adds the initial migration log table -- this should likely be
|
|
|
|
|
// automatic and first, but enough tests exists that do not expect that we can keep it explicit
|
|
|
|
|
func (mg *Migrator) AddCreateMigration() {
|
|
|
|
|
mg.AddMigration("create "+mg.tableName+" table", NewAddTableMigration(Table{
|
|
|
|
|
Name: mg.tableName,
|
|
|
|
|
Columns: []*Column{
|
|
|
|
|
{Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
|
|
|
|
{Name: "migration_id", Type: DB_NVarchar, Length: 255},
|
|
|
|
|
{Name: "sql", Type: DB_Text},
|
|
|
|
|
{Name: "success", Type: DB_Bool},
|
|
|
|
|
{Name: "error", Type: DB_Text},
|
|
|
|
|
{Name: "timestamp", Type: DB_DateTime},
|
|
|
|
|
},
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-14 22:30:12 +08:00
|
|
|
func (mg *Migrator) MigrationsCount() int {
|
|
|
|
|
return len(mg.migrations)
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 01:41:03 +08:00
|
|
|
func (mg *Migrator) AddMigration(id string, m Migration) {
|
2022-06-04 07:59:49 +08:00
|
|
|
if _, ok := mg.migrationIds[id]; ok {
|
|
|
|
|
panic(fmt.Sprintf("migration id conflict: %s", id))
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 01:41:03 +08:00
|
|
|
m.SetId(id)
|
|
|
|
|
mg.migrations = append(mg.migrations, m)
|
2022-06-04 07:59:49 +08:00
|
|
|
mg.migrationIds[id] = struct{}{}
|
2015-01-19 01:41:03 +08:00
|
|
|
}
|
|
|
|
|
|
2021-11-25 03:56:07 +08:00
|
|
|
func (mg *Migrator) GetMigrationIDs(excludeNotLogged bool) []string {
|
|
|
|
|
result := make([]string, 0, len(mg.migrations))
|
|
|
|
|
for _, migration := range mg.migrations {
|
|
|
|
|
if migration.SkipMigrationLog() && excludeNotLogged {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
result = append(result, migration.Id())
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 01:41:03 +08:00
|
|
|
func (mg *Migrator) GetMigrationLog() (map[string]MigrationLog, error) {
|
2015-01-19 17:44:16 +08:00
|
|
|
logMap := make(map[string]MigrationLog)
|
|
|
|
|
logItems := make([]MigrationLog, 0)
|
|
|
|
|
|
2023-05-23 02:31:07 +08:00
|
|
|
exists, err := mg.DBEngine.IsTableExist(mg.tableName)
|
2015-01-19 01:41:03 +08:00
|
|
|
if err != nil {
|
2022-06-03 15:24:24 +08:00
|
|
|
return nil, fmt.Errorf("%v: %w", "failed to check table existence", err)
|
2015-01-19 01:41:03 +08:00
|
|
|
}
|
|
|
|
|
if !exists {
|
2015-01-19 17:44:16 +08:00
|
|
|
return logMap, nil
|
2015-01-19 01:41:03 +08:00
|
|
|
}
|
|
|
|
|
|
2023-05-23 02:31:07 +08:00
|
|
|
if err = mg.DBEngine.Table(mg.tableName).Find(&logItems); err != nil {
|
2015-01-19 01:41:03 +08:00
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, logItem := range logItems {
|
|
|
|
|
if !logItem.Success {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2020-11-11 13:21:08 +08:00
|
|
|
logMap[logItem.MigrationID] = logItem
|
2015-01-19 01:41:03 +08:00
|
|
|
}
|
|
|
|
|
|
2023-04-19 23:34:19 +08:00
|
|
|
mg.logMap = logMap
|
2015-01-19 01:41:03 +08:00
|
|
|
return logMap, nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 23:34:19 +08:00
|
|
|
func (mg *Migrator) RemoveMigrationLogs(migrationsIDs ...string) {
|
|
|
|
|
for _, id := range migrationsIDs {
|
|
|
|
|
delete(mg.logMap, id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-16 00:54:27 +08:00
|
|
|
func (mg *Migrator) Start(isDatabaseLockingEnabled bool, lockAttemptTimeout int) (err error) {
|
|
|
|
|
if !isDatabaseLockingEnabled {
|
|
|
|
|
return mg.run()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mg.InTransaction(func(sess *xorm.Session) error {
|
|
|
|
|
mg.Logger.Info("Locking database")
|
|
|
|
|
if err := casRestoreOnErr(&mg.isLocked, false, true, ErrMigratorIsLocked, mg.Dialect.Lock, LockCfg{Session: sess, Timeout: lockAttemptTimeout}); err != nil {
|
|
|
|
|
mg.Logger.Error("Failed to lock database", "error", err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
|
mg.Logger.Info("Unlocking database")
|
|
|
|
|
unlockErr := casRestoreOnErr(&mg.isLocked, true, false, ErrMigratorIsUnlocked, mg.Dialect.Unlock, LockCfg{Session: sess})
|
|
|
|
|
if unlockErr != nil {
|
|
|
|
|
mg.Logger.Error("Failed to unlock database", "error", unlockErr)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
// migration will run inside a nested transaction
|
|
|
|
|
return mg.run()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (mg *Migrator) run() (err error) {
|
2020-07-23 21:47:26 +08:00
|
|
|
mg.Logger.Info("Starting DB migrations")
|
2015-01-19 01:41:03 +08:00
|
|
|
|
2023-04-19 23:34:19 +08:00
|
|
|
_, err = mg.GetMigrationLog()
|
2015-01-19 01:41:03 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-08 04:26:29 +08:00
|
|
|
migrationsPerformed := 0
|
|
|
|
|
migrationsSkipped := 0
|
|
|
|
|
start := time.Now()
|
2015-01-19 01:41:03 +08:00
|
|
|
for _, m := range mg.migrations {
|
2020-06-29 23:04:38 +08:00
|
|
|
m := m
|
2023-04-19 23:34:19 +08:00
|
|
|
_, exists := mg.logMap[m.Id()]
|
2015-01-19 01:41:03 +08:00
|
|
|
if exists {
|
2016-06-07 05:06:44 +08:00
|
|
|
mg.Logger.Debug("Skipping migration: Already executed", "id", m.Id())
|
2021-03-08 04:26:29 +08:00
|
|
|
migrationsSkipped++
|
2015-01-19 01:41:03 +08:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-11 13:21:08 +08:00
|
|
|
sql := m.SQL(mg.Dialect)
|
2015-01-19 17:44:16 +08:00
|
|
|
|
2015-01-19 01:41:03 +08:00
|
|
|
record := MigrationLog{
|
2020-11-11 13:21:08 +08:00
|
|
|
MigrationID: m.Id(),
|
|
|
|
|
SQL: sql,
|
2015-01-19 01:41:03 +08:00
|
|
|
Timestamp: time.Now(),
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-14 21:43:33 +08:00
|
|
|
err := mg.InTransaction(func(sess *xorm.Session) error {
|
Outdent code after if block that ends with return (golint)
This commit fixes the following golint warnings:
pkg/bus/bus.go:64:9: if block ends with a return statement, so drop this else and outdent its block
pkg/bus/bus.go:84:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:137:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:177:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:183:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:199:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:208:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/components/dynmap/dynmap.go:236:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:242:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:257:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:263:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:278:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:284:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:299:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:331:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:350:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:356:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:366:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:390:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:396:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:405:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:427:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:433:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:442:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:459:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:465:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:474:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:491:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:497:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:506:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:523:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:529:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:538:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:555:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:561:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:570:12: if block ends with a return statement, so drop this else and outdent its block
pkg/login/ldap.go:55:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/login/ldap_test.go:372:10: if block ends with a return statement, so drop this else and outdent its block
pkg/middleware/middleware_test.go:213:12: if block ends with a return statement, so drop this else and outdent its block
pkg/plugins/dashboard_importer.go:153:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/dashboards_updater.go:39:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/dashboards_updater.go:121:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/plugins.go:210:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/plugins.go:235:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/eval_context.go:111:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:92:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:98:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:122:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:108:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:118:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:121:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifiers/telegram.go:94:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/annotation.go:34:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/annotation.go:99:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/dashboard_test.go:107:13: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/plugin_setting.go:78:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/preferences.go:91:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/user.go:50:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/migrator/migrator.go:106:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/migrator/postgres_dialect.go:48:10: if block ends with a return statement, so drop this else and outdent its block
pkg/tsdb/time_range.go:59:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/tsdb/time_range.go:67:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/tsdb/cloudwatch/metric_find_query.go:225:9: if block ends with a return statement, so drop this else and outdent its block
pkg/util/filepath.go:68:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
2018-04-28 04:42:49 +08:00
|
|
|
err := mg.exec(m, sess)
|
|
|
|
|
if err != nil {
|
2016-09-30 13:49:40 +08:00
|
|
|
mg.Logger.Error("Exec failed", "error", err, "sql", sql)
|
|
|
|
|
record.Error = err.Error()
|
2021-08-12 21:04:09 +08:00
|
|
|
if !m.SkipMigrationLog() {
|
2023-05-23 02:31:07 +08:00
|
|
|
if _, err := sess.Table(mg.tableName).Insert(&record); err != nil {
|
2021-08-12 21:04:09 +08:00
|
|
|
return err
|
|
|
|
|
}
|
2019-10-22 20:08:18 +08:00
|
|
|
}
|
2016-09-30 13:49:40 +08:00
|
|
|
return err
|
|
|
|
|
}
|
Outdent code after if block that ends with return (golint)
This commit fixes the following golint warnings:
pkg/bus/bus.go:64:9: if block ends with a return statement, so drop this else and outdent its block
pkg/bus/bus.go:84:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:137:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:177:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:183:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:199:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:208:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/components/dynmap/dynmap.go:236:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:242:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:257:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:263:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:278:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:284:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:299:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:331:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:350:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:356:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:366:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:390:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:396:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:405:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:427:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:433:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:442:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:459:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:465:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:474:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:491:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:497:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:506:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:523:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:529:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:538:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:555:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:561:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:570:12: if block ends with a return statement, so drop this else and outdent its block
pkg/login/ldap.go:55:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/login/ldap_test.go:372:10: if block ends with a return statement, so drop this else and outdent its block
pkg/middleware/middleware_test.go:213:12: if block ends with a return statement, so drop this else and outdent its block
pkg/plugins/dashboard_importer.go:153:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/dashboards_updater.go:39:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/dashboards_updater.go:121:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/plugins.go:210:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/plugins.go:235:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/eval_context.go:111:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:92:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:98:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:122:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:108:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:118:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:121:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifiers/telegram.go:94:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/annotation.go:34:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/annotation.go:99:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/dashboard_test.go:107:13: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/plugin_setting.go:78:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/preferences.go:91:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/user.go:50:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/migrator/migrator.go:106:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/migrator/postgres_dialect.go:48:10: if block ends with a return statement, so drop this else and outdent its block
pkg/tsdb/time_range.go:59:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/tsdb/time_range.go:67:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/tsdb/cloudwatch/metric_find_query.go:225:9: if block ends with a return statement, so drop this else and outdent its block
pkg/util/filepath.go:68:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
2018-04-28 04:42:49 +08:00
|
|
|
record.Success = true
|
2021-08-12 21:04:09 +08:00
|
|
|
if !m.SkipMigrationLog() {
|
2023-05-23 02:31:07 +08:00
|
|
|
_, err = sess.Table(mg.tableName).Insert(&record)
|
2021-08-12 21:04:09 +08:00
|
|
|
}
|
2021-03-08 04:26:29 +08:00
|
|
|
if err == nil {
|
|
|
|
|
migrationsPerformed++
|
|
|
|
|
}
|
2019-10-22 20:08:18 +08:00
|
|
|
return err
|
2016-09-30 13:49:40 +08:00
|
|
|
})
|
|
|
|
|
if err != nil {
|
2022-06-03 15:24:24 +08:00
|
|
|
return fmt.Errorf("%v: %w", fmt.Sprintf("migration failed (id = %s)", m.Id()), err)
|
2015-01-19 01:41:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-08 04:26:29 +08:00
|
|
|
mg.Logger.Info("migrations completed", "performed", migrationsPerformed, "skipped", migrationsSkipped, "duration", time.Since(start))
|
|
|
|
|
|
2021-01-07 18:36:13 +08:00
|
|
|
// Make sure migrations are synced
|
2021-11-25 03:56:07 +08:00
|
|
|
return mg.DBEngine.Sync2()
|
2015-01-19 01:41:03 +08:00
|
|
|
}
|
|
|
|
|
|
2016-09-30 13:49:40 +08:00
|
|
|
func (mg *Migrator) exec(m Migration, sess *xorm.Session) error {
|
2016-06-11 17:38:25 +08:00
|
|
|
mg.Logger.Info("Executing migration", "id", m.Id())
|
2015-01-19 01:41:03 +08:00
|
|
|
|
2016-09-30 13:49:40 +08:00
|
|
|
condition := m.GetCondition()
|
|
|
|
|
if condition != nil {
|
2020-11-11 13:21:08 +08:00
|
|
|
sql, args := condition.SQL(mg.Dialect)
|
2018-12-19 04:47:45 +08:00
|
|
|
|
2018-12-19 06:02:08 +08:00
|
|
|
if sql != "" {
|
2021-01-07 18:36:13 +08:00
|
|
|
mg.Logger.Debug("Executing migration condition SQL", "id", m.Id(), "sql", sql, "args", args)
|
2018-12-19 06:02:08 +08:00
|
|
|
results, err := sess.SQL(sql, args...).Query()
|
|
|
|
|
if err != nil {
|
|
|
|
|
mg.Logger.Error("Executing migration condition failed", "id", m.Id(), "error", err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !condition.IsFulfilled(results) {
|
|
|
|
|
mg.Logger.Warn("Skipping migration: Already executed, but not recorded in migration log", "id", m.Id())
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2015-02-24 18:46:34 +08:00
|
|
|
}
|
2016-09-30 13:49:40 +08:00
|
|
|
}
|
2015-02-24 18:46:34 +08:00
|
|
|
|
2018-08-21 19:30:39 +08:00
|
|
|
var err error
|
|
|
|
|
if codeMigration, ok := m.(CodeMigration); ok {
|
2018-12-19 04:47:45 +08:00
|
|
|
mg.Logger.Debug("Executing code migration", "id", m.Id())
|
2018-08-21 19:30:39 +08:00
|
|
|
err = codeMigration.Exec(sess, mg)
|
|
|
|
|
} else {
|
2020-11-11 13:21:08 +08:00
|
|
|
sql := m.SQL(mg.Dialect)
|
2018-12-19 04:47:45 +08:00
|
|
|
mg.Logger.Debug("Executing sql migration", "id", m.Id(), "sql", sql)
|
|
|
|
|
_, err = sess.Exec(sql)
|
2018-08-21 19:30:39 +08:00
|
|
|
}
|
|
|
|
|
|
2016-09-30 13:49:40 +08:00
|
|
|
if err != nil {
|
|
|
|
|
mg.Logger.Error("Executing migration failed", "id", m.Id(), "error", err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
2015-01-19 01:41:03 +08:00
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type dbTransactionFunc func(sess *xorm.Session) error
|
|
|
|
|
|
2021-06-14 21:43:33 +08:00
|
|
|
func (mg *Migrator) InTransaction(callback dbTransactionFunc) error {
|
2021-11-25 03:56:07 +08:00
|
|
|
sess := mg.DBEngine.NewSession()
|
2015-01-19 01:41:03 +08:00
|
|
|
defer sess.Close()
|
|
|
|
|
|
2019-10-22 20:08:18 +08:00
|
|
|
if err := sess.Begin(); err != nil {
|
2015-01-19 01:41:03 +08:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-22 20:08:18 +08:00
|
|
|
if err := callback(sess); err != nil {
|
2021-01-07 18:36:13 +08:00
|
|
|
if rollErr := sess.Rollback(); rollErr != nil {
|
2022-06-07 04:30:31 +08:00
|
|
|
return fmt.Errorf("failed to roll back transaction due to error: %s: %w", rollErr, err)
|
2019-10-22 20:08:18 +08:00
|
|
|
}
|
2015-01-19 01:41:03 +08:00
|
|
|
|
|
|
|
|
return err
|
2019-10-22 20:08:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := sess.Commit(); err != nil {
|
2015-01-19 01:41:03 +08:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2022-02-16 00:54:27 +08:00
|
|
|
|
|
|
|
|
func casRestoreOnErr(lock *atomic.Bool, o, n bool, casErr error, f func(LockCfg) error, lockCfg LockCfg) error {
|
2022-12-14 19:32:45 +08:00
|
|
|
if !lock.CompareAndSwap(o, n) {
|
2022-02-16 00:54:27 +08:00
|
|
|
return casErr
|
|
|
|
|
}
|
|
|
|
|
if err := f(lockCfg); err != nil {
|
|
|
|
|
// Automatically unlock/lock on error
|
|
|
|
|
lock.Store(o)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|