From 235c093bb97d37cdfa34103b59eabacfde9b2a42 Mon Sep 17 00:00:00 2001 From: Cr <631807682@qq.com> Date: Wed, 29 Jun 2022 10:07:42 +0800 Subject: [PATCH] fix(MigrateColumn):declared different type without length (#5465) --- migrator/migrator.go | 11 +++++++---- tests/migrate_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index f20bf513..87ac7745 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -15,7 +15,6 @@ import ( ) var ( - regRealDataType = regexp.MustCompile(`[^\d](\d+)[^\d]?`) regFullDataType = regexp.MustCompile(`[^\d]*(\d+)[^\d]?`) ) @@ -404,11 +403,16 @@ func (m Migrator) RenameColumn(value interface{}, oldName, newName string) error // MigrateColumn migrate column func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnType gorm.ColumnType) error { // found, smart migrate - fullDataType := strings.ToLower(m.DB.Migrator().FullDataTypeOf(field).SQL) + fullDataType := strings.TrimSpace(strings.ToLower(m.DB.Migrator().FullDataTypeOf(field).SQL)) realDataType := strings.ToLower(columnType.DatabaseTypeName()) alterColumn := false + // check type + if !field.PrimaryKey && !strings.HasPrefix(fullDataType, realDataType) { + alterColumn = true + } + // check size if length, ok := columnType.Length(); length != int64(field.Size) { if length > 0 && field.Size > 0 { @@ -416,9 +420,8 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy } else { // has size in data type and not equal // Since the following code is frequently called in the for loop, reg optimization is needed here - matches := regRealDataType.FindAllStringSubmatch(realDataType, -1) matches2 := regFullDataType.FindAllStringSubmatch(fullDataType, -1) - if (len(matches) == 1 && matches[0][1] != fmt.Sprint(field.Size) || !field.PrimaryKey) && + if !field.PrimaryKey && (len(matches2) == 1 && matches2[0][1] != fmt.Sprint(length) && ok) { alterColumn = true } diff --git a/tests/migrate_test.go b/tests/migrate_test.go index 9e7caec9..0bbef382 100644 --- a/tests/migrate_test.go +++ b/tests/migrate_test.go @@ -884,3 +884,42 @@ func TestInvalidCachedPlan(t *testing.T) { t.Errorf("AutoMigrate err:%v", err) } } + +func TestDifferentTypeWithoutDeclaredLength(t *testing.T) { + type DiffType struct { + ID uint + Name string `gorm:"type:varchar(20)"` + } + + type DiffType1 struct { + ID uint + Name string `gorm:"type:text"` + } + + var err error + DB.Migrator().DropTable(&DiffType{}) + + err = DB.AutoMigrate(&DiffType{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } + + ct, err := findColumnType(&DiffType{}, "name") + if err != nil { + t.Errorf("findColumnType err:%v", err) + } + + AssertEqual(t, "varchar", strings.ToLower(ct.DatabaseTypeName())) + + err = DB.Table("diff_types").AutoMigrate(&DiffType1{}) + if err != nil { + t.Errorf("AutoMigrate err:%v", err) + } + + ct, err = findColumnType(&DiffType{}, "name") + if err != nil { + t.Errorf("findColumnType err:%v", err) + } + + AssertEqual(t, "text", strings.ToLower(ct.DatabaseTypeName())) +}