Skip to content

Commit f757b8f

Browse files
authored
fix: auto migration column order unpredictable (#4980)
1 parent b47cf57 commit f757b8f

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

migrator/migrator.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,20 @@ func (m Migrator) AutoMigrate(values ...interface{}) error {
9797
if err := m.RunWithValue(value, func(stmt *gorm.Statement) (errr error) {
9898
columnTypes, _ := m.DB.Migrator().ColumnTypes(value)
9999

100-
for _, field := range stmt.Schema.FieldsByDBName {
100+
for _, dbName := range stmt.Schema.DBNames {
101+
field := stmt.Schema.FieldsByDBName[dbName]
101102
var foundColumn gorm.ColumnType
102103

103104
for _, columnType := range columnTypes {
104-
if columnType.Name() == field.DBName {
105+
if columnType.Name() == dbName {
105106
foundColumn = columnType
106107
break
107108
}
108109
}
109110

110111
if foundColumn == nil {
111112
// not found, add column
112-
if err := tx.Migrator().AddColumn(value, field.DBName); err != nil {
113+
if err := tx.Migrator().AddColumn(value, dbName); err != nil {
113114
return err
114115
}
115116
} else if err := m.DB.Migrator().MigrateColumn(value, field, foundColumn); err != nil {

tests/migrate_test.go

+72
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package tests_test
22

33
import (
44
"math/rand"
5+
"reflect"
56
"strings"
67
"testing"
78
"time"
89

910
"gorm.io/gorm"
11+
"gorm.io/gorm/schema"
1012
. "gorm.io/gorm/utils/tests"
1113
)
1214

@@ -454,3 +456,73 @@ func TestMigrateIndexesWithDynamicTableName(t *testing.T) {
454456
}
455457
}
456458
}
459+
460+
// check column order after migration, flaky test
461+
// https://github.com/go-gorm/gorm/issues/4351
462+
func TestMigrateColumnOrder(t *testing.T) {
463+
type UserMigrateColumn struct {
464+
ID uint
465+
}
466+
DB.Migrator().DropTable(&UserMigrateColumn{})
467+
DB.AutoMigrate(&UserMigrateColumn{})
468+
469+
type UserMigrateColumn2 struct {
470+
ID uint
471+
F1 string
472+
F2 string
473+
F3 string
474+
F4 string
475+
F5 string
476+
F6 string
477+
F7 string
478+
F8 string
479+
F9 string
480+
F10 string
481+
F11 string
482+
F12 string
483+
F13 string
484+
F14 string
485+
F15 string
486+
F16 string
487+
F17 string
488+
F18 string
489+
F19 string
490+
F20 string
491+
F21 string
492+
F22 string
493+
F23 string
494+
F24 string
495+
F25 string
496+
F26 string
497+
F27 string
498+
F28 string
499+
F29 string
500+
F30 string
501+
F31 string
502+
F32 string
503+
F33 string
504+
F34 string
505+
F35 string
506+
}
507+
if err := DB.Table("user_migrate_columns").AutoMigrate(&UserMigrateColumn2{}); err != nil {
508+
t.Fatalf("failed to auto migrate, got error: %v", err)
509+
}
510+
511+
columnTypes, err := DB.Table("user_migrate_columns").Migrator().ColumnTypes(&UserMigrateColumn2{})
512+
if err != nil {
513+
t.Fatalf("failed to get column types, got error: %v", err)
514+
}
515+
typ := reflect.Indirect(reflect.ValueOf(&UserMigrateColumn2{})).Type()
516+
numField := typ.NumField()
517+
if numField != len(columnTypes) {
518+
t.Fatalf("column's number not match struct and ddl, %d != %d", numField, len(columnTypes))
519+
}
520+
namer := schema.NamingStrategy{}
521+
for i := 0; i < numField; i++ {
522+
expectName := namer.ColumnName("", typ.Field(i).Name)
523+
if columnTypes[i].Name() != expectName {
524+
t.Fatalf("column order not match struct and ddl, idx %d: %s != %s",
525+
i, columnTypes[i].Name(), expectName)
526+
}
527+
}
528+
}

0 commit comments

Comments
 (0)