fix: auto migration column order unpredictable
This commit is contained in:
		
							parent
							
								
									4dd2647967
								
							
						
					
					
						commit
						f605175cf3
					
				@ -97,11 +97,12 @@ func (m Migrator) AutoMigrate(values ...interface{}) error {
 | 
				
			|||||||
			if err := m.RunWithValue(value, func(stmt *gorm.Statement) (errr error) {
 | 
								if err := m.RunWithValue(value, func(stmt *gorm.Statement) (errr error) {
 | 
				
			||||||
				columnTypes, _ := m.DB.Migrator().ColumnTypes(value)
 | 
									columnTypes, _ := m.DB.Migrator().ColumnTypes(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for _, field := range stmt.Schema.FieldsByDBName {
 | 
									for _, dbName := range stmt.Schema.DBNames {
 | 
				
			||||||
 | 
										field := stmt.Schema.FieldsByDBName[dbName]
 | 
				
			||||||
					var foundColumn gorm.ColumnType
 | 
										var foundColumn gorm.ColumnType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					for _, columnType := range columnTypes {
 | 
										for _, columnType := range columnTypes {
 | 
				
			||||||
						if columnType.Name() == field.DBName {
 | 
											if columnType.Name() == dbName {
 | 
				
			||||||
							foundColumn = columnType
 | 
												foundColumn = columnType
 | 
				
			||||||
							break
 | 
												break
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
@ -109,7 +110,7 @@ func (m Migrator) AutoMigrate(values ...interface{}) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					if foundColumn == nil {
 | 
										if foundColumn == nil {
 | 
				
			||||||
						// not found, add column
 | 
											// not found, add column
 | 
				
			||||||
						if err := tx.Migrator().AddColumn(value, field.DBName); err != nil {
 | 
											if err := tx.Migrator().AddColumn(value, dbName); err != nil {
 | 
				
			||||||
							return err
 | 
												return err
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					} else if err := m.DB.Migrator().MigrateColumn(value, field, foundColumn); err != nil {
 | 
										} else if err := m.DB.Migrator().MigrateColumn(value, field, foundColumn); err != nil {
 | 
				
			||||||
 | 
				
			|||||||
@ -2,11 +2,13 @@ package tests_test
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"math/rand"
 | 
						"math/rand"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"gorm.io/gorm"
 | 
						"gorm.io/gorm"
 | 
				
			||||||
 | 
						"gorm.io/gorm/schema"
 | 
				
			||||||
	. "gorm.io/gorm/utils/tests"
 | 
						. "gorm.io/gorm/utils/tests"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -455,3 +457,73 @@ func TestMigrateIndexesWithDynamicTableName(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// check column order after migration, flaky test
 | 
				
			||||||
 | 
					// https://github.com/go-gorm/gorm/issues/4351
 | 
				
			||||||
 | 
					func TestMigrateColumnOrder(t *testing.T) {
 | 
				
			||||||
 | 
						type UserMigrateColumn struct {
 | 
				
			||||||
 | 
							ID uint
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						DB.Migrator().DropTable(&UserMigrateColumn{})
 | 
				
			||||||
 | 
						DB.AutoMigrate(&UserMigrateColumn{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type UserMigrateColumn2 struct {
 | 
				
			||||||
 | 
							ID  uint
 | 
				
			||||||
 | 
							F1  string
 | 
				
			||||||
 | 
							F2  string
 | 
				
			||||||
 | 
							F3  string
 | 
				
			||||||
 | 
							F4  string
 | 
				
			||||||
 | 
							F5  string
 | 
				
			||||||
 | 
							F6  string
 | 
				
			||||||
 | 
							F7  string
 | 
				
			||||||
 | 
							F8  string
 | 
				
			||||||
 | 
							F9  string
 | 
				
			||||||
 | 
							F10 string
 | 
				
			||||||
 | 
							F11 string
 | 
				
			||||||
 | 
							F12 string
 | 
				
			||||||
 | 
							F13 string
 | 
				
			||||||
 | 
							F14 string
 | 
				
			||||||
 | 
							F15 string
 | 
				
			||||||
 | 
							F16 string
 | 
				
			||||||
 | 
							F17 string
 | 
				
			||||||
 | 
							F18 string
 | 
				
			||||||
 | 
							F19 string
 | 
				
			||||||
 | 
							F20 string
 | 
				
			||||||
 | 
							F21 string
 | 
				
			||||||
 | 
							F22 string
 | 
				
			||||||
 | 
							F23 string
 | 
				
			||||||
 | 
							F24 string
 | 
				
			||||||
 | 
							F25 string
 | 
				
			||||||
 | 
							F26 string
 | 
				
			||||||
 | 
							F27 string
 | 
				
			||||||
 | 
							F28 string
 | 
				
			||||||
 | 
							F29 string
 | 
				
			||||||
 | 
							F30 string
 | 
				
			||||||
 | 
							F31 string
 | 
				
			||||||
 | 
							F32 string
 | 
				
			||||||
 | 
							F33 string
 | 
				
			||||||
 | 
							F34 string
 | 
				
			||||||
 | 
							F35 string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := DB.Table("user_migrate_columns").AutoMigrate(&UserMigrateColumn2{}); err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("failed to auto migrate, got error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						columnTypes, err := DB.Table("user_migrate_columns").Migrator().ColumnTypes(&UserMigrateColumn2{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatalf("failed to get column types, got error: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						typ := reflect.Indirect(reflect.ValueOf(&UserMigrateColumn2{})).Type()
 | 
				
			||||||
 | 
						numField := typ.NumField()
 | 
				
			||||||
 | 
						if numField != len(columnTypes) {
 | 
				
			||||||
 | 
							t.Fatalf("column's number not match struct and ddl, %d != %d", numField, len(columnTypes))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						namer := schema.NamingStrategy{}
 | 
				
			||||||
 | 
						for i := 0; i < numField; i++ {
 | 
				
			||||||
 | 
							expectName := namer.ColumnName("", typ.Field(i).Name)
 | 
				
			||||||
 | 
							if columnTypes[i].Name() != expectName {
 | 
				
			||||||
 | 
								t.Fatalf("column order not match struct and ddl, idx %d: %s != %s",
 | 
				
			||||||
 | 
									i, columnTypes[i].Name(), expectName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user