fix: migrate column default value (#5359)
Co-authored-by: Jinzhu <wosmvp@gmail.com>
This commit is contained in:
		
							parent
							
								
									dc1ae394f3
								
							
						
					
					
						commit
						93986de8e4
					
				| @ -448,10 +448,20 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// check default value
 | 	// check default value
 | ||||||
| 	if v, ok := columnType.DefaultValue(); ok && v != field.DefaultValue { |  | ||||||
| 		// not primary key
 |  | ||||||
| 	if !field.PrimaryKey { | 	if !field.PrimaryKey { | ||||||
|  | 		dv, dvNotNull := columnType.DefaultValue() | ||||||
|  | 		if dvNotNull && field.DefaultValueInterface == nil { | ||||||
|  | 			// defalut value -> null
 | ||||||
| 			alterColumn = true | 			alterColumn = true | ||||||
|  | 		} else if !dvNotNull && field.DefaultValueInterface != nil { | ||||||
|  | 			// null -> default value
 | ||||||
|  | 			alterColumn = true | ||||||
|  | 		} else if dv != field.DefaultValue { | ||||||
|  | 			// default value not equal
 | ||||||
|  | 			// not both null
 | ||||||
|  | 			if !(field.DefaultValueInterface == nil && !dvNotNull) { | ||||||
|  | 				alterColumn = true | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package tests_test | package tests_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"math/rand" | 	"math/rand" | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"strings" | 	"strings" | ||||||
| @ -714,6 +715,141 @@ func TestPrimarykeyID(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func TestUniqueColumn(t *testing.T) { | ||||||
|  | 	if DB.Dialector.Name() != "mysql" { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type UniqueTest struct { | ||||||
|  | 		ID   string `gorm:"primary_key"` | ||||||
|  | 		Name string `gorm:"unique"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type UniqueTest2 struct { | ||||||
|  | 		ID   string `gorm:"primary_key"` | ||||||
|  | 		Name string `gorm:"unique;default:NULL"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type UniqueTest3 struct { | ||||||
|  | 		ID   string `gorm:"primary_key"` | ||||||
|  | 		Name string `gorm:"unique;default:''"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type UniqueTest4 struct { | ||||||
|  | 		ID   string `gorm:"primary_key"` | ||||||
|  | 		Name string `gorm:"unique;default:'123'"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var err error | ||||||
|  | 	err = DB.Migrator().DropTable(&UniqueTest{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("DropTable err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = DB.AutoMigrate(&UniqueTest{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("AutoMigrate err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// null -> null
 | ||||||
|  | 	err = DB.AutoMigrate(&UniqueTest{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("AutoMigrate err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ct, err := findColumnType(&UniqueTest{}, "name") | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("findColumnType err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	value, ok := ct.DefaultValue() | ||||||
|  | 	AssertEqual(t, "", value) | ||||||
|  | 	AssertEqual(t, false, ok) | ||||||
|  | 
 | ||||||
|  | 	// null -> null
 | ||||||
|  | 	err = DB.Table("unique_tests").AutoMigrate(&UniqueTest2{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("AutoMigrate err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// not trigger alert column
 | ||||||
|  | 	AssertEqual(t, true, DB.Migrator().HasIndex(&UniqueTest{}, "name")) | ||||||
|  | 	AssertEqual(t, false, DB.Migrator().HasIndex(&UniqueTest{}, "name_1")) | ||||||
|  | 	AssertEqual(t, false, DB.Migrator().HasIndex(&UniqueTest{}, "name_2")) | ||||||
|  | 
 | ||||||
|  | 	ct, err = findColumnType(&UniqueTest{}, "name") | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("findColumnType err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	value, ok = ct.DefaultValue() | ||||||
|  | 	AssertEqual(t, "", value) | ||||||
|  | 	AssertEqual(t, false, ok) | ||||||
|  | 
 | ||||||
|  | 	// null -> empty string
 | ||||||
|  | 	err = DB.Table("unique_tests").AutoMigrate(&UniqueTest3{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("AutoMigrate err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ct, err = findColumnType(&UniqueTest{}, "name") | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("findColumnType err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	value, ok = ct.DefaultValue() | ||||||
|  | 	AssertEqual(t, "", value) | ||||||
|  | 	AssertEqual(t, true, ok) | ||||||
|  | 
 | ||||||
|  | 	//  empty string -> 123
 | ||||||
|  | 	err = DB.Table("unique_tests").AutoMigrate(&UniqueTest4{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("AutoMigrate err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ct, err = findColumnType(&UniqueTest{}, "name") | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("findColumnType err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	value, ok = ct.DefaultValue() | ||||||
|  | 	AssertEqual(t, "123", value) | ||||||
|  | 	AssertEqual(t, true, ok) | ||||||
|  | 
 | ||||||
|  | 	//  123 -> null
 | ||||||
|  | 	err = DB.Table("unique_tests").AutoMigrate(&UniqueTest2{}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("AutoMigrate err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ct, err = findColumnType(&UniqueTest{}, "name") | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("findColumnType err:%v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	value, ok = ct.DefaultValue() | ||||||
|  | 	AssertEqual(t, "", value) | ||||||
|  | 	AssertEqual(t, false, ok) | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func findColumnType(dest interface{}, columnName string) ( | ||||||
|  | 	foundColumn gorm.ColumnType, err error) { | ||||||
|  | 	columnTypes, err := DB.Migrator().ColumnTypes(dest) | ||||||
|  | 	if err != nil { | ||||||
|  | 		err = fmt.Errorf("ColumnTypes err:%v", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, c := range columnTypes { | ||||||
|  | 		if c.Name() == columnName { | ||||||
|  | 			foundColumn = c | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestInvalidCachedPlan(t *testing.T) { | func TestInvalidCachedPlan(t *testing.T) { | ||||||
| 	if DB.Dialector.Name() != "postgres" { | 	if DB.Dialector.Name() != "postgres" { | ||||||
| 		return | 		return | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Cr
						Cr