diff --git a/pkg/services/sqlstore/migrations/ualert/alert_rule_version_guid_mig.go b/pkg/services/sqlstore/migrations/ualert/alert_rule_version_guid_mig.go index 600167f4829..3713e4eaa0a 100644 --- a/pkg/services/sqlstore/migrations/ualert/alert_rule_version_guid_mig.go +++ b/pkg/services/sqlstore/migrations/ualert/alert_rule_version_guid_mig.go @@ -1,9 +1,13 @@ package ualert import ( + "fmt" + "strings" + "github.com/google/uuid" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" + "github.com/grafana/grafana/pkg/util" "xorm.io/xorm" ) @@ -58,26 +62,59 @@ func (c setRuleGuidMigration) SQL(migrator.Dialect) string { } func (c setRuleGuidMigration) Exec(sess *xorm.Session, mg *migrator.Migrator) error { - var results []string - if err := sess.SQL("SELECT uid FROM alert_rule").Find(&results); err != nil { - return err - } - if len(results) == 0 { - mg.Logger.Debug("no rules found") - return nil - } - for _, uid := range results { - u := uuid.NewString() - _, err := sess.Exec("UPDATE alert_rule_version SET rule_guid = ? WHERE rule_uid = ?", u, uid) - if err != nil { - mg.Logger.Error("Failed to update alert_rule_version table", "error", err) + var lastId *int64 + for { + var results []int64 + qq := sess.Table(`alert_rule`).Select("id").OrderBy("id").Limit(500) + if lastId != nil { + qq = qq.Where("id > ?", lastId) + } + if err := qq.Find(&results); err != nil { return err } - _, err = sess.Exec("UPDATE alert_rule SET guid = ? WHERE uid = ?", u, uid) + if len(results) == 0 { + break + } + bd := strings.Builder{} + for idx, id := range results { + u := uuid.NewString() + if idx == 0 { + bd.WriteString(fmt.Sprintf("SELECT %d as id, '%s' as guid", id, u)) + continue + } + bd.WriteString(fmt.Sprintf(" UNION ALL SELECT %d, '%s' ", id, u)) + } + var q string + if mg.Dialect.DriverName() == migrator.MySQL { + q = fmt.Sprintf(`UPDATE alert_rule AS ar + INNER JOIN (%s) AS t ON ar.id = t.id + SET ar.guid = t.guid;`, bd.String()) + } else { + q = fmt.Sprintf(`UPDATE alert_rule SET guid = t.guid FROM (%s) AS t WHERE alert_rule.id = t.id`, bd.String()) + } + _, err := sess.Exec(q) if err != nil { mg.Logger.Error("Failed to update alert_rule table", "error", err) return err } + lastId = util.Pointer(results[len(results)-1]) + } + + q := `UPDATE alert_rule_version + SET rule_guid = alert_rule.guid + FROM alert_rule + WHERE alert_rule.uid = alert_rule_version.rule_uid + AND alert_rule.org_id = alert_rule_version.rule_org_id;` + + if mg.Dialect.DriverName() == migrator.MySQL { + q = `UPDATE alert_rule_version AS arv + INNER JOIN alert_rule AS ar ON arv.rule_uid = ar.uid AND arv.rule_org_id = ar.org_id + SET arv.rule_guid = ar.guid;` + } + _, err := sess.Exec(q) + if err != nil { + mg.Logger.Error("Failed to update alert_rule_version table with GUIDs from alert_rule table", "error", err) + return err } return nil }