Skip to content

Commit

Permalink
Improve support for AutoMigrate
Browse files Browse the repository at this point in the history
  • Loading branch information
jinzhu committed Feb 19, 2022
1 parent e0b4e0e commit 48ced75
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 19 deletions.
4 changes: 2 additions & 2 deletions migrator/column_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type ColumnType struct {
NameValue sql.NullString
DataTypeValue sql.NullString
ColumnTypeValue sql.NullString
PrimayKeyValue sql.NullBool
PrimaryKeyValue sql.NullBool
UniqueValue sql.NullBool
AutoIncrementValue sql.NullBool
LengthValue sql.NullInt64
Expand Down Expand Up @@ -51,7 +51,7 @@ func (ct ColumnType) ColumnType() (columnType string, ok bool) {

// PrimaryKey returns the column is primary key or not.
func (ct ColumnType) PrimaryKey() (isPrimaryKey bool, ok bool) {
return ct.PrimayKeyValue.Bool, ct.PrimayKeyValue.Valid
return ct.PrimaryKeyValue.Bool, ct.PrimaryKeyValue.Valid
}

// AutoIncrement returns the column is auto increment or not.
Expand Down
24 changes: 24 additions & 0 deletions migrator/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,30 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy
}
}

// check unique
if unique, ok := columnType.Unique(); ok && unique != field.Unique {
// not primary key
if !field.PrimaryKey {
alterColumn = true
}
}

// check default value
if v, ok := columnType.DefaultValue(); ok && v != field.DefaultValue {
// not primary key
if !field.PrimaryKey {
alterColumn = true
}
}

// check comment
if comment, ok := columnType.Comment(); ok && comment != field.Comment {
// not primary key
if !field.PrimaryKey {
alterColumn = true
}
}

if alterColumn && !field.IgnoreMigration {
return m.DB.Migrator().AlterColumn(value, field.Name)
}
Expand Down
10 changes: 5 additions & 5 deletions tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ require (
github.com/lib/pq v1.10.4
github.com/mattn/go-sqlite3 v1.14.11 // indirect
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
gorm.io/driver/mysql v1.3.0
gorm.io/driver/postgres v1.3.0
gorm.io/driver/sqlite v1.3.0
gorm.io/driver/sqlserver v1.3.0
gorm.io/gorm v1.22.5
gorm.io/driver/mysql v1.3.1
gorm.io/driver/postgres v1.3.1
gorm.io/driver/sqlite v1.3.1
gorm.io/driver/sqlserver v1.3.1
gorm.io/gorm v1.23.0
)

replace gorm.io/gorm => ../
47 changes: 35 additions & 12 deletions tests/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestMigrate(t *testing.T) {

for _, m := range allModels {
if !DB.Migrator().HasTable(m) {
t.Fatalf("Failed to create table for %#v---", m)
t.Fatalf("Failed to create table for %#v", m)
}
}

Expand Down Expand Up @@ -313,15 +313,16 @@ func TestMigrateIndexes(t *testing.T) {
}

func TestMigrateColumns(t *testing.T) {
fullSupported := map[string]bool{"sqlite": true, "mysql": true, "postgres": true, "sqlserver": true}[DB.Dialector.Name()]
sqlite := DB.Dialector.Name() == "sqlite"
sqlserver := DB.Dialector.Name() == "sqlserver"

type ColumnStruct struct {
gorm.Model
Name string
Age int `gorm:"default:18;comment:my age"`
Code string `gorm:"unique"`
Name string
Age int `gorm:"default:18;comment:my age"`
Code string `gorm:"unique;comment:my code;"`
Code2 string
Code3 string `gorm:"unique"`
}

DB.Migrator().DropTable(&ColumnStruct{})
Expand All @@ -332,13 +333,20 @@ func TestMigrateColumns(t *testing.T) {

type ColumnStruct2 struct {
gorm.Model
Name string `gorm:"size:100"`
Name string `gorm:"size:100"`
Code string `gorm:"unique;comment:my code2;default:hello"`
Code2 string `gorm:"unique"`
// Code3 string
}

if err := DB.Table("column_structs").Migrator().AlterColumn(&ColumnStruct2{}, "Name"); err != nil {
if err := DB.Table("column_structs").Migrator().AlterColumn(&ColumnStruct{}, "Name"); err != nil {
t.Fatalf("no error should happened when alter column, but got %v", err)
}

if err := DB.Table("column_structs").AutoMigrate(&ColumnStruct2{}); err != nil {
t.Fatalf("no error should happened when auto migrate column, but got %v", err)
}

if columnTypes, err := DB.Migrator().ColumnTypes(&ColumnStruct{}); err != nil {
t.Fatalf("no error should returns for ColumnTypes")
} else {
Expand All @@ -348,28 +356,43 @@ func TestMigrateColumns(t *testing.T) {
for _, columnType := range columnTypes {
switch columnType.Name() {
case "id":
if v, ok := columnType.PrimaryKey(); (fullSupported || ok) && !v {
if v, ok := columnType.PrimaryKey(); !ok || !v {
t.Fatalf("column id primary key should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
case "name":
dataType := DB.Dialector.DataTypeOf(stmt.Schema.LookUpField(columnType.Name()))
if !strings.Contains(strings.ToUpper(dataType), strings.ToUpper(columnType.DatabaseTypeName())) {
t.Fatalf("column name type should be correct, name: %v, length: %v, expects: %v, column: %#v", columnType.Name(), columnType.DatabaseTypeName(), dataType, columnType)
}
if length, ok := columnType.Length(); ((fullSupported && !sqlite) || ok) && length != 100 {
if length, ok := columnType.Length(); !sqlite && (!ok || length != 100) {
t.Fatalf("column name length should be correct, name: %v, length: %v, expects: %v, column: %#v", columnType.Name(), length, 100, columnType)
}
case "age":
if v, ok := columnType.DefaultValue(); (fullSupported || ok) && v != "18" {
if v, ok := columnType.DefaultValue(); !ok || v != "18" {
t.Fatalf("column age default value should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
if v, ok := columnType.Comment(); ((fullSupported && !sqlite && !sqlserver) || ok) && v != "my age" {
if v, ok := columnType.Comment(); !sqlite && !sqlserver && (!ok || v != "my age") {
t.Fatalf("column age comment should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
case "code":
if v, ok := columnType.Unique(); (fullSupported || ok) && !v {
if v, ok := columnType.Unique(); !ok || !v {
t.Fatalf("column code unique should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
if v, ok := columnType.DefaultValue(); !sqlserver && (!ok || v != "hello") {
t.Fatalf("column code default value should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
if v, ok := columnType.Comment(); !sqlite && !sqlserver && (!ok || v != "my code2") {
t.Fatalf("column code comment should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
case "code2":
if v, ok := columnType.Unique(); !sqlserver && (!ok || !v) {
t.Fatalf("column code2 unique should be correct, name: %v, column: %#v", columnType.Name(), columnType)
}
case "code3":
// TODO
// if v, ok := columnType.Unique(); !ok || v {
// t.Fatalf("column code unique should be correct, name: %v, column: %#v", columnType.Name(), columnType)
// }
}
}
}
Expand Down

0 comments on commit 48ced75

Please sign in to comment.