From 12f3c8f9d677f00c14c44da2425990555824afd4 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Tue, 18 Dec 2018 23:02:08 +0100 Subject: [PATCH] fix only add column if not exists for mysql --- pkg/services/sqlstore/migrator/conditions.go | 10 +++++++++ pkg/services/sqlstore/migrator/dialect.go | 5 +++++ pkg/services/sqlstore/migrator/migrations.go | 4 +++- pkg/services/sqlstore/migrator/migrator.go | 21 +++++++++++-------- .../sqlstore/migrator/mysql_dialect.go | 6 ++++++ 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/pkg/services/sqlstore/migrator/conditions.go b/pkg/services/sqlstore/migrator/conditions.go index b9b145de326..b6adfdbfa29 100644 --- a/pkg/services/sqlstore/migrator/conditions.go +++ b/pkg/services/sqlstore/migrator/conditions.go @@ -36,3 +36,13 @@ type IfIndexNotExistsCondition struct { func (c *IfIndexNotExistsCondition) Sql(dialect Dialect) (string, []interface{}) { return dialect.IndexCheckSql(c.TableName, c.IndexName) } + +type IfColumnNotExistsCondition struct { + NotExistsMigrationCondition + TableName string + ColumnName string +} + +func (c *IfColumnNotExistsCondition) Sql(dialect Dialect) (string, []interface{}) { + return dialect.ColumnCheckSql(c.TableName, c.ColumnName) +} diff --git a/pkg/services/sqlstore/migrator/dialect.go b/pkg/services/sqlstore/migrator/dialect.go index e8ea07e007c..d2e3c3e0777 100644 --- a/pkg/services/sqlstore/migrator/dialect.go +++ b/pkg/services/sqlstore/migrator/dialect.go @@ -33,6 +33,7 @@ type Dialect interface { UpdateTableSql(tableName string, columns []*Column) string IndexCheckSql(tableName, indexName string) (string, []interface{}) + ColumnCheckSql(tableName, columnName string) (string, []interface{}) ColString(*Column) string ColStringNoPk(*Column) string @@ -183,6 +184,10 @@ func (db *BaseDialect) RenameTable(oldName string, newName string) string { return fmt.Sprintf("ALTER TABLE %s RENAME TO %s", quote(oldName), quote(newName)) } +func (db *BaseDialect) ColumnCheckSql(tableName, columnName string) (string, []interface{}) { + return "", nil +} + func (db *BaseDialect) DropIndexSql(tableName string, index *Index) string { quote := db.dialect.Quote name := index.XName(tableName) diff --git a/pkg/services/sqlstore/migrator/migrations.go b/pkg/services/sqlstore/migrator/migrations.go index d5a4158c52a..cb32c6212e6 100644 --- a/pkg/services/sqlstore/migrator/migrations.go +++ b/pkg/services/sqlstore/migrator/migrations.go @@ -85,7 +85,9 @@ type AddColumnMigration struct { } func NewAddColumnMigration(table Table, col *Column) *AddColumnMigration { - return &AddColumnMigration{tableName: table.Name, column: col} + m := &AddColumnMigration{tableName: table.Name, column: col} + m.Condition = &IfColumnNotExistsCondition{TableName: table.Name, ColumnName: col.Name} + return m } func (m *AddColumnMigration) Table(tableName string) *AddColumnMigration { diff --git a/pkg/services/sqlstore/migrator/migrator.go b/pkg/services/sqlstore/migrator/migrator.go index b99d397f365..ce0b2663def 100644 --- a/pkg/services/sqlstore/migrator/migrator.go +++ b/pkg/services/sqlstore/migrator/migrator.go @@ -121,16 +121,19 @@ func (mg *Migrator) exec(m Migration, sess *xorm.Session) error { condition := m.GetCondition() if condition != nil { sql, args := condition.Sql(mg.Dialect) - mg.Logger.Debug("Executing migration condition sql", "id", m.Id(), "sql", sql, "args", args) - 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 + if sql != "" { + mg.Logger.Debug("Executing migration condition sql", "id", m.Id(), "sql", sql, "args", args) + 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 + } } } diff --git a/pkg/services/sqlstore/migrator/mysql_dialect.go b/pkg/services/sqlstore/migrator/mysql_dialect.go index b5e16d8c500..4de55c9a12f 100644 --- a/pkg/services/sqlstore/migrator/mysql_dialect.go +++ b/pkg/services/sqlstore/migrator/mysql_dialect.go @@ -108,6 +108,12 @@ func (db *Mysql) IndexCheckSql(tableName, indexName string) (string, []interface return sql, args } +func (db *Mysql) ColumnCheckSql(tableName, columnName string) (string, []interface{}) { + args := []interface{}{tableName, columnName} + sql := "SELECT 1 FROM " + db.Quote("INFORMATION_SCHEMA") + "." + db.Quote("COLUMNS") + " WHERE " + db.Quote("TABLE_SCHEMA") + " = DATABASE() AND " + db.Quote("TABLE_NAME") + "=? AND " + db.Quote("COLUMN_NAME") + "=?" + return sql, args +} + func (db *Mysql) CleanDB() error { tables, _ := db.engine.DBMetas() sess := db.engine.NewSession()