Fix: wrong value when Find with Join with same column name, close #5723, #5711

This commit is contained in:
Stephano George 2022-09-30 17:18:42 +08:00 committed by Jinzhu
parent be440e7512
commit a3cc6c6088
3 changed files with 47 additions and 19 deletions

31
scan.go
View File

@ -163,11 +163,10 @@ func Scan(rows Rows, db *DB, mode ScanMode) {
} }
default: default:
var ( var (
fields = make([]*schema.Field, len(columns)) fields = make([]*schema.Field, len(columns))
selectedColumnsMap = make(map[string]int, len(columns)) joinFields [][2]*schema.Field
joinFields [][2]*schema.Field sch = db.Statement.Schema
sch = db.Statement.Schema reflectValue = db.Statement.ReflectValue
reflectValue = db.Statement.ReflectValue
) )
if reflectValue.Kind() == reflect.Interface { if reflectValue.Kind() == reflect.Interface {
@ -200,26 +199,24 @@ func Scan(rows Rows, db *DB, mode ScanMode) {
// Not Pluck // Not Pluck
if sch != nil { if sch != nil {
schFieldsCount := len(sch.Fields) matchedFieldCount := make(map[string]int, len(columns))
for idx, column := range columns { for idx, column := range columns {
if field := sch.LookUpField(column); field != nil && field.Readable { if field := sch.LookUpField(column); field != nil && field.Readable {
if curIndex, ok := selectedColumnsMap[column]; ok { fields[idx] = field
fields[idx] = field // handle duplicate fields if count, ok := matchedFieldCount[column]; ok {
offset := curIndex + 1 // handle duplicate fields
// handle sch inconsistent with database for _, selectField := range sch.Fields {
// like Raw(`...`).Scan if selectField.DBName == column && selectField.Readable {
if schFieldsCount > offset { if count == 0 {
for fieldIndex, selectField := range sch.Fields[offset:] { matchedFieldCount[column]++
if selectField.DBName == column && selectField.Readable {
selectedColumnsMap[column] = curIndex + fieldIndex + 1
fields[idx] = selectField fields[idx] = selectField
break break
} }
count--
} }
} }
} else { } else {
fields[idx] = field matchedFieldCount[column] = 1
selectedColumnsMap[column] = idx
} }
} else if names := strings.Split(column, "__"); len(names) > 1 { } else if names := strings.Split(column, "__"); len(names) > 1 {
if rel, ok := sch.Relationships.Relations[names[0]]; ok { if rel, ok := sch.Relationships.Relations[names[0]]; ok {

View File

@ -9,12 +9,12 @@ require (
github.com/jinzhu/now v1.1.5 github.com/jinzhu/now v1.1.5
github.com/lib/pq v1.10.7 github.com/lib/pq v1.10.7
github.com/mattn/go-sqlite3 v1.14.15 // indirect github.com/mattn/go-sqlite3 v1.14.15 // indirect
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 // indirect golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be // indirect
gorm.io/driver/mysql v1.3.6 gorm.io/driver/mysql v1.3.6
gorm.io/driver/postgres v1.3.10 gorm.io/driver/postgres v1.3.10
gorm.io/driver/sqlite v1.3.6 gorm.io/driver/sqlite v1.3.6
gorm.io/driver/sqlserver v1.3.2 gorm.io/driver/sqlserver v1.3.2
gorm.io/gorm v1.23.9 gorm.io/gorm v1.23.10
) )
replace gorm.io/gorm => ../ replace gorm.io/gorm => ../

View File

@ -229,3 +229,34 @@ func TestJoinWithSoftDeleted(t *testing.T) {
t.Fatalf("joins NamedPet and Account should not empty:%v", user2) t.Fatalf("joins NamedPet and Account should not empty:%v", user2)
} }
} }
func TestJoinWithSameColumnName(t *testing.T) {
user := GetUser("TestJoinWithSameColumnName", Config{
Languages: 1,
Pets: 1,
})
DB.Create(user)
type UserSpeak struct {
UserID uint
LanguageCode string
}
type Result struct {
User
UserSpeak
Language
Pet
}
results := make([]Result, 0, 1)
DB.Select("users.*, user_speaks.*, languages.*, pets.*").Table("users").Joins("JOIN user_speaks ON user_speaks.user_id = users.id").
Joins("JOIN languages ON languages.code = user_speaks.language_code").
Joins("LEFT OUTER JOIN pets ON pets.user_id = users.id").Find(&results)
if len(results) == 0 {
t.Fatalf("no record find")
} else if results[0].Pet.UserID == nil || *(results[0].Pet.UserID) != user.ID {
t.Fatalf("wrong user id in pet")
} else if results[0].Pet.Name != user.Pets[0].Name {
t.Fatalf("wrong pet name")
}
}