Skip to content

Commit

Permalink
Fix scanning identical column names occurring >2 times (go-gorm#2080)
Browse files Browse the repository at this point in the history
Fix the indexing logic used in selectedColumnsMap to skip fields
that have already been seen. The values of selectedColumns map
must be indexed relative to fields, not relative to selectFields.
  • Loading branch information
xyziemba authored and jinzhu committed Sep 9, 2018
1 parent dc3b247 commit 71b7f19
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
54 changes: 54 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,60 @@ func TestJoins(t *testing.T) {
}
}

type JoinedIds struct {
UserID int64 `gorm:"column:id"`
BillingAddressID int64 `gorm:"column:id"`
EmailID int64 `gorm:"column:id"`
}

func TestScanIdenticalColumnNames(t *testing.T) {
var user = User{
Name: "joinsIds",
Email: "joinIds@example.com",
BillingAddress: Address{
Address1: "One Park Place",
},
Emails: []Email{{Email: "join1@example.com"}, {Email: "join2@example.com"}},
}
DB.Save(&user)

var users []JoinedIds
DB.Select("users.id, addresses.id, emails.id").Table("users").
Joins("left join addresses on users.billing_address_id = addresses.id").
Joins("left join emails on emails.user_id = users.id").
Where("name = ?", "joinsIds").Scan(&users)

if len(users) != 2 {
t.Fatal("should find two rows using left join")
}

if user.Id != users[0].UserID {
t.Errorf("Expected result row to contain UserID %d, but got %d", user.Id, users[0].UserID)
}
if user.Id != users[1].UserID {
t.Errorf("Expected result row to contain UserID %d, but got %d", user.Id, users[1].UserID)
}

if user.BillingAddressID.Int64 != users[0].BillingAddressID {
t.Errorf("Expected result row to contain BillingAddressID %d, but got %d", user.BillingAddressID.Int64, users[0].BillingAddressID)
}
if user.BillingAddressID.Int64 != users[1].BillingAddressID {
t.Errorf("Expected result row to contain BillingAddressID %d, but got %d", user.BillingAddressID.Int64, users[0].BillingAddressID)
}

if users[0].EmailID == users[1].EmailID {
t.Errorf("Email ids should be unique. Got %d and %d", users[0].EmailID, users[1].EmailID)
}

if int64(user.Emails[0].Id) != users[0].EmailID && int64(user.Emails[1].Id) != users[0].EmailID {
t.Errorf("Expected result row ID to be either %d or %d, but was %d", user.Emails[0].Id, user.Emails[1].Id, users[0].EmailID)
}

if int64(user.Emails[0].Id) != users[1].EmailID && int64(user.Emails[1].Id) != users[1].EmailID {
t.Errorf("Expected result row ID to be either %d or %d, but was %d", user.Emails[0].Id, user.Emails[1].Id, users[1].EmailID)
}
}

func TestJoinsWithSelect(t *testing.T) {
type result struct {
Name string
Expand Down
6 changes: 4 additions & 2 deletions scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,10 @@ func (scope *Scope) scan(rows *sql.Rows, columns []string, fields []*Field) {
values[index] = &ignored

selectFields = fields
offset := 0
if idx, ok := selectedColumnsMap[column]; ok {
selectFields = selectFields[idx+1:]
offset = idx + 1
selectFields = selectFields[offset:]
}

for fieldIndex, field := range selectFields {
Expand All @@ -501,7 +503,7 @@ func (scope *Scope) scan(rows *sql.Rows, columns []string, fields []*Field) {
resetFields[index] = field
}

selectedColumnsMap[column] = fieldIndex
selectedColumnsMap[column] = offset + fieldIndex

if field.IsNormal {
break
Expand Down

0 comments on commit 71b7f19

Please sign in to comment.