Skip to content

Commit

Permalink
fix: migrator force modification of fields with no default value (#134)
Browse files Browse the repository at this point in the history
* fix: migrator force modification of fields with no default value

* test: re-migrate table fields with or without default value
  • Loading branch information
iTanken authored Jun 17, 2024
1 parent 15fe45b commit 64af933
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
2 changes: 0 additions & 2 deletions migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,6 @@ func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) {
column.DefaultValueValue.String = matches[1]
matches = defaultValueTrimRegexp.FindStringSubmatch(column.DefaultValueValue.String)
}
} else {
column.DefaultValueValue.Valid = true
}

for _, c := range rawColumnTypes {
Expand Down
73 changes: 73 additions & 0 deletions migrator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package sqlserver_test

import (
"os"
"reflect"
"testing"
"time"

"gorm.io/driver/sqlserver"
"gorm.io/gorm"
Expand Down Expand Up @@ -115,3 +117,74 @@ func TestCreateIndex(t *testing.T) {
t.Error("couldn't drop table testtable", tx.Error)
}
}

type TestTableDefaultValue struct {
ID string `gorm:"column:id;primaryKey"`
Name string `gorm:"column:name"`
Age uint `gorm:"column:age"`
Birthday *time.Time `gorm:"column:birthday"`
CompanyID *int `gorm:"column:company_id;default:0"`
ManagerID *uint `gorm:"column:manager_id;default:0"`
Active bool `gorm:"column:active;default:1"`
}

func (*TestTableDefaultValue) TableName() string { return "test_table_default_value" }

func TestReMigrateTableFieldsWithoutDefaultValue(t *testing.T) {
db, err := gorm.Open(sqlserver.Open(sqlserverDSN))
if err != nil {
t.Error(err)
}

var (
migrator = db.Migrator()
tableModel = new(TestTableDefaultValue)
fieldsWithDefault = []string{"company_id", "manager_id", "active"}
fieldsWithoutDefault = []string{"id", "name", "age", "birthday"}

columnsWithDefault []string
columnsWithoutDefault []string
)

defer func() {
if err = migrator.DropTable(tableModel); err != nil {
t.Errorf("couldn't drop table %q, got error: %v", tableModel.TableName(), err)
}
}()
if !migrator.HasTable(tableModel) {
if err = migrator.AutoMigrate(tableModel); err != nil {
t.Errorf("couldn't auto migrate table %q, got error: %v", tableModel.TableName(), err)
}
}
// If in the `Migrator.ColumnTypes` method `column.DefaultValueValue.Valid = true`,
// re-migrate the table will alter all fields without default value except for the primary key.
if err = db.Debug().Migrator().AutoMigrate(tableModel); err != nil {
t.Errorf("couldn't re-migrate table %q, got error: %v", tableModel.TableName(), err)
}

columnsWithDefault, columnsWithoutDefault, err = testGetMigrateColumns(db, tableModel)
if !reflect.DeepEqual(columnsWithDefault, fieldsWithDefault) {
// If in the `Migrator.ColumnTypes` method `column.DefaultValueValue.Valid = true`,
// fields with default value will include all fields: `[id name age birthday company_id manager_id active]`.
t.Errorf("expected columns with default value %v, got %v", fieldsWithDefault, columnsWithDefault)
}
if !reflect.DeepEqual(columnsWithoutDefault, fieldsWithoutDefault) {
t.Errorf("expected columns without default value %v, got %v", fieldsWithoutDefault, columnsWithoutDefault)
}
}

func testGetMigrateColumns(db *gorm.DB, dst interface{}) (columnsWithDefault, columnsWithoutDefault []string, err error) {
migrator := db.Migrator()
var columnTypes []gorm.ColumnType
if columnTypes, err = migrator.ColumnTypes(dst); err != nil {
return
}
for _, columnType := range columnTypes {
if _, ok := columnType.DefaultValue(); ok {
columnsWithDefault = append(columnsWithDefault, columnType.Name())
} else {
columnsWithoutDefault = append(columnsWithoutDefault, columnType.Name())
}
}
return
}

0 comments on commit 64af933

Please sign in to comment.