forked from mirror/gorm
Improve support for AutoMigrate
This commit is contained in:
parent
e0b4e0ec8f
commit
48ced75d1d
|
@ -11,7 +11,7 @@ type ColumnType struct {
|
||||||
NameValue sql.NullString
|
NameValue sql.NullString
|
||||||
DataTypeValue sql.NullString
|
DataTypeValue sql.NullString
|
||||||
ColumnTypeValue sql.NullString
|
ColumnTypeValue sql.NullString
|
||||||
PrimayKeyValue sql.NullBool
|
PrimaryKeyValue sql.NullBool
|
||||||
UniqueValue sql.NullBool
|
UniqueValue sql.NullBool
|
||||||
AutoIncrementValue sql.NullBool
|
AutoIncrementValue sql.NullBool
|
||||||
LengthValue sql.NullInt64
|
LengthValue sql.NullInt64
|
||||||
|
@ -51,7 +51,7 @@ func (ct ColumnType) ColumnType() (columnType string, ok bool) {
|
||||||
|
|
||||||
// PrimaryKey returns the column is primary key or not.
|
// PrimaryKey returns the column is primary key or not.
|
||||||
func (ct ColumnType) PrimaryKey() (isPrimaryKey bool, ok bool) {
|
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.
|
// AutoIncrement returns the column is auto increment or not.
|
||||||
|
|
|
@ -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 {
|
if alterColumn && !field.IgnoreMigration {
|
||||||
return m.DB.Migrator().AlterColumn(value, field.Name)
|
return m.DB.Migrator().AlterColumn(value, field.Name)
|
||||||
}
|
}
|
||||||
|
|
10
tests/go.mod
10
tests/go.mod
|
@ -9,11 +9,11 @@ require (
|
||||||
github.com/lib/pq v1.10.4
|
github.com/lib/pq v1.10.4
|
||||||
github.com/mattn/go-sqlite3 v1.14.11 // indirect
|
github.com/mattn/go-sqlite3 v1.14.11 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||||
gorm.io/driver/mysql v1.3.0
|
gorm.io/driver/mysql v1.3.1
|
||||||
gorm.io/driver/postgres v1.3.0
|
gorm.io/driver/postgres v1.3.1
|
||||||
gorm.io/driver/sqlite v1.3.0
|
gorm.io/driver/sqlite v1.3.1
|
||||||
gorm.io/driver/sqlserver v1.3.0
|
gorm.io/driver/sqlserver v1.3.1
|
||||||
gorm.io/gorm v1.22.5
|
gorm.io/gorm v1.23.0
|
||||||
)
|
)
|
||||||
|
|
||||||
replace gorm.io/gorm => ../
|
replace gorm.io/gorm => ../
|
||||||
|
|
|
@ -45,7 +45,7 @@ func TestMigrate(t *testing.T) {
|
||||||
|
|
||||||
for _, m := range allModels {
|
for _, m := range allModels {
|
||||||
if !DB.Migrator().HasTable(m) {
|
if !DB.Migrator().HasTable(m) {
|
||||||
t.Fatalf("Failed to create table for %#v---", m)
|
t.Fatalf("Failed to create table for %#v", m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,15 +313,16 @@ func TestMigrateIndexes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMigrateColumns(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"
|
sqlite := DB.Dialector.Name() == "sqlite"
|
||||||
sqlserver := DB.Dialector.Name() == "sqlserver"
|
sqlserver := DB.Dialector.Name() == "sqlserver"
|
||||||
|
|
||||||
type ColumnStruct struct {
|
type ColumnStruct struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name string
|
Name string
|
||||||
Age int `gorm:"default:18;comment:my age"`
|
Age int `gorm:"default:18;comment:my age"`
|
||||||
Code string `gorm:"unique"`
|
Code string `gorm:"unique;comment:my code;"`
|
||||||
|
Code2 string
|
||||||
|
Code3 string `gorm:"unique"`
|
||||||
}
|
}
|
||||||
|
|
||||||
DB.Migrator().DropTable(&ColumnStruct{})
|
DB.Migrator().DropTable(&ColumnStruct{})
|
||||||
|
@ -332,13 +333,20 @@ func TestMigrateColumns(t *testing.T) {
|
||||||
|
|
||||||
type ColumnStruct2 struct {
|
type ColumnStruct2 struct {
|
||||||
gorm.Model
|
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)
|
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 {
|
if columnTypes, err := DB.Migrator().ColumnTypes(&ColumnStruct{}); err != nil {
|
||||||
t.Fatalf("no error should returns for ColumnTypes")
|
t.Fatalf("no error should returns for ColumnTypes")
|
||||||
} else {
|
} else {
|
||||||
|
@ -348,7 +356,7 @@ func TestMigrateColumns(t *testing.T) {
|
||||||
for _, columnType := range columnTypes {
|
for _, columnType := range columnTypes {
|
||||||
switch columnType.Name() {
|
switch columnType.Name() {
|
||||||
case "id":
|
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)
|
t.Fatalf("column id primary key should be correct, name: %v, column: %#v", columnType.Name(), columnType)
|
||||||
}
|
}
|
||||||
case "name":
|
case "name":
|
||||||
|
@ -356,20 +364,35 @@ func TestMigrateColumns(t *testing.T) {
|
||||||
if !strings.Contains(strings.ToUpper(dataType), strings.ToUpper(columnType.DatabaseTypeName())) {
|
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)
|
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)
|
t.Fatalf("column name length should be correct, name: %v, length: %v, expects: %v, column: %#v", columnType.Name(), length, 100, columnType)
|
||||||
}
|
}
|
||||||
case "age":
|
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)
|
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)
|
t.Fatalf("column age comment should be correct, name: %v, column: %#v", columnType.Name(), columnType)
|
||||||
}
|
}
|
||||||
case "code":
|
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)
|
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)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue