2015-02-11 08:43:53 +03:00
|
|
|
package gorm_test
|
|
|
|
|
2015-04-21 10:00:36 +03:00
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"log"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
)
|
2015-03-12 12:47:31 +03:00
|
|
|
|
|
|
|
func getPreloadUser(name string) *User {
|
|
|
|
return getPreparedUser(name, "Preload")
|
2015-02-11 10:37:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func checkUserHasPreloadData(user User, t *testing.T) {
|
|
|
|
u := getPreloadUser(user.Name)
|
|
|
|
if user.BillingAddress.Address1 != u.BillingAddress.Address1 {
|
|
|
|
t.Error("Failed to preload user's BillingAddress")
|
|
|
|
}
|
|
|
|
|
|
|
|
if user.ShippingAddress.Address1 != u.ShippingAddress.Address1 {
|
|
|
|
t.Error("Failed to preload user's ShippingAddress")
|
|
|
|
}
|
|
|
|
|
|
|
|
if user.CreditCard.Number != u.CreditCard.Number {
|
|
|
|
t.Error("Failed to preload user's CreditCard")
|
|
|
|
}
|
|
|
|
|
2015-02-12 08:46:49 +03:00
|
|
|
if user.Company.Name != u.Company.Name {
|
|
|
|
t.Error("Failed to preload user's Company")
|
|
|
|
}
|
|
|
|
|
2015-02-11 10:37:04 +03:00
|
|
|
if len(user.Emails) != len(u.Emails) {
|
|
|
|
t.Error("Failed to preload user's Emails")
|
|
|
|
} else {
|
|
|
|
var found int
|
|
|
|
for _, e1 := range u.Emails {
|
|
|
|
for _, e2 := range user.Emails {
|
|
|
|
if e1.Email == e2.Email {
|
|
|
|
found++
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if found != len(u.Emails) {
|
|
|
|
t.Error("Failed to preload user's email details")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-02-11 08:43:53 +03:00
|
|
|
|
|
|
|
func TestPreload(t *testing.T) {
|
2015-02-11 10:37:04 +03:00
|
|
|
user1 := getPreloadUser("user1")
|
2015-03-12 12:47:31 +03:00
|
|
|
DB.Save(user1)
|
2015-02-11 10:37:04 +03:00
|
|
|
|
2015-02-12 08:46:49 +03:00
|
|
|
preloadDB := DB.Where("role = ?", "Preload").Preload("BillingAddress").Preload("ShippingAddress").
|
|
|
|
Preload("CreditCard").Preload("Emails").Preload("Company")
|
2015-02-11 10:37:04 +03:00
|
|
|
var user User
|
2015-02-12 08:46:49 +03:00
|
|
|
preloadDB.Find(&user)
|
2015-02-11 10:37:04 +03:00
|
|
|
checkUserHasPreloadData(user, t)
|
|
|
|
|
|
|
|
user2 := getPreloadUser("user2")
|
2015-03-12 12:47:31 +03:00
|
|
|
DB.Save(user2)
|
2015-02-11 10:37:04 +03:00
|
|
|
|
|
|
|
user3 := getPreloadUser("user3")
|
2015-03-12 12:47:31 +03:00
|
|
|
DB.Save(user3)
|
2015-02-11 08:43:53 +03:00
|
|
|
|
|
|
|
var users []User
|
2015-02-12 08:46:49 +03:00
|
|
|
preloadDB.Find(&users)
|
2015-02-11 10:37:04 +03:00
|
|
|
|
|
|
|
for _, user := range users {
|
|
|
|
checkUserHasPreloadData(user, t)
|
|
|
|
}
|
2015-02-11 12:58:19 +03:00
|
|
|
|
|
|
|
var users2 []*User
|
2015-02-12 08:46:49 +03:00
|
|
|
preloadDB.Find(&users2)
|
2015-02-11 12:58:19 +03:00
|
|
|
|
|
|
|
for _, user := range users2 {
|
|
|
|
checkUserHasPreloadData(*user, t)
|
|
|
|
}
|
2015-02-11 14:08:42 +03:00
|
|
|
|
|
|
|
var users3 []*User
|
2015-02-12 08:46:49 +03:00
|
|
|
preloadDB.Preload("Emails", "email = ?", user3.Emails[0].Email).Find(&users3)
|
2015-02-11 14:08:42 +03:00
|
|
|
|
|
|
|
for _, user := range users3 {
|
|
|
|
if user.Name == user3.Name {
|
|
|
|
if len(user.Emails) != 1 {
|
|
|
|
t.Errorf("should only preload one emails for user3 when with condition")
|
|
|
|
}
|
|
|
|
} else if len(user.Emails) != 0 {
|
|
|
|
t.Errorf("should not preload any emails for other users when with condition")
|
|
|
|
}
|
|
|
|
}
|
2015-02-11 08:43:53 +03:00
|
|
|
}
|
2015-04-21 10:00:36 +03:00
|
|
|
|
|
|
|
func TestNestedPreload(t *testing.T) {
|
|
|
|
log.SetFlags(log.Lshortfile)
|
|
|
|
// Struct: Level3
|
|
|
|
{
|
|
|
|
type (
|
|
|
|
Level1 struct {
|
|
|
|
ID uint
|
|
|
|
Value string
|
|
|
|
Level2ID uint
|
|
|
|
}
|
|
|
|
Level2 struct {
|
|
|
|
ID uint
|
|
|
|
Level1 Level1
|
|
|
|
Level3ID uint
|
|
|
|
}
|
|
|
|
Level3 struct {
|
|
|
|
ID uint
|
|
|
|
Level2 Level2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
DB.DropTableIfExists(&Level3{})
|
|
|
|
DB.DropTableIfExists(&Level2{})
|
|
|
|
DB.DropTableIfExists(&Level1{})
|
|
|
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := Level3{Level2: Level2{Level1: Level1{Value: "value"}}}
|
|
|
|
if err := DB.Create(&want).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var got Level3
|
|
|
|
if err := DB.Preload("Level2").Preload("Level2.Level1").Find(&got).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
type (
|
|
|
|
Level1 struct {
|
|
|
|
ID uint
|
|
|
|
Value string
|
|
|
|
Level2ID uint
|
|
|
|
}
|
|
|
|
Level2 struct {
|
|
|
|
ID uint
|
|
|
|
Level1s []Level1
|
|
|
|
Level3ID uint
|
|
|
|
}
|
|
|
|
Level3 struct {
|
|
|
|
ID uint
|
|
|
|
Level2s []Level2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
DB.DropTableIfExists(&Level3{})
|
|
|
|
DB.DropTableIfExists(&Level2{})
|
|
|
|
DB.DropTableIfExists(&Level1{})
|
|
|
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := Level3{
|
|
|
|
Level2s: []Level2{
|
|
|
|
{
|
|
|
|
Level1s: []Level1{
|
|
|
|
{Value: "value1"},
|
|
|
|
{Value: "value2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Level1s: []Level1{
|
|
|
|
{Value: "value3"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var got Level3
|
|
|
|
if err := DB.Preload("Level2s.Level1s").Find(&got).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
type (
|
|
|
|
Level1 struct {
|
|
|
|
ID uint
|
|
|
|
Value string
|
|
|
|
Level2ID uint
|
|
|
|
}
|
|
|
|
Level2 struct {
|
|
|
|
ID uint
|
|
|
|
Level1 Level1
|
|
|
|
Level3ID uint
|
|
|
|
}
|
|
|
|
Level3 struct {
|
|
|
|
ID uint
|
|
|
|
Level2s []Level2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
DB.DropTableIfExists(&Level3{})
|
|
|
|
DB.DropTableIfExists(&Level2{})
|
|
|
|
DB.DropTableIfExists(&Level1{})
|
|
|
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := Level3{
|
|
|
|
Level2s: []Level2{
|
|
|
|
{Level1: Level1{Value: "value1"}},
|
|
|
|
{Level1: Level1{Value: "value2"}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var got Level3
|
|
|
|
if err := DB.Preload("Level2s.Level1").Find(&got).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
type (
|
|
|
|
Level1 struct {
|
|
|
|
ID uint
|
|
|
|
Value string
|
|
|
|
Level2ID uint
|
|
|
|
}
|
|
|
|
Level2 struct {
|
|
|
|
ID uint
|
|
|
|
Level1s []Level1
|
|
|
|
Level3ID uint
|
|
|
|
}
|
|
|
|
Level3 struct {
|
|
|
|
ID uint
|
|
|
|
Level2 Level2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
DB.DropTableIfExists(&Level3{})
|
|
|
|
DB.DropTableIfExists(&Level2{})
|
|
|
|
DB.DropTableIfExists(&Level1{})
|
|
|
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := Level3{
|
|
|
|
Level2: Level2{
|
|
|
|
Level1s: []Level1{
|
|
|
|
Level1{Value: "value1"},
|
|
|
|
Level1{Value: "value2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var got Level3
|
|
|
|
if err := DB.Preload("Level2.Level1s").Find(&got).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Slice: []Level3
|
|
|
|
{
|
|
|
|
type (
|
|
|
|
Level1 struct {
|
|
|
|
ID uint
|
|
|
|
Value string
|
|
|
|
Level2ID uint
|
|
|
|
}
|
|
|
|
Level2 struct {
|
|
|
|
ID uint
|
|
|
|
Level1 Level1
|
|
|
|
Level3ID uint
|
|
|
|
}
|
|
|
|
Level3 struct {
|
|
|
|
ID uint
|
|
|
|
Level2 Level2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
DB.DropTableIfExists(&Level3{})
|
|
|
|
DB.DropTableIfExists(&Level2{})
|
|
|
|
DB.DropTableIfExists(&Level1{})
|
|
|
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := make([]Level3, 2)
|
|
|
|
want[0] = Level3{Level2: Level2{Level1: Level1{Value: "value"}}}
|
|
|
|
if err := DB.Create(&want[0]).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
want[1] = Level3{Level2: Level2{Level1: Level1{Value: "value2"}}}
|
|
|
|
if err := DB.Create(&want[1]).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var got []Level3
|
|
|
|
if err := DB.Preload("Level2").Preload("Level2.Level1").Find(&got).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
type (
|
|
|
|
Level1 struct {
|
|
|
|
ID uint
|
|
|
|
Value string
|
|
|
|
Level2ID uint
|
|
|
|
}
|
|
|
|
Level2 struct {
|
|
|
|
ID uint
|
|
|
|
Level1s []Level1
|
|
|
|
Level3ID uint
|
|
|
|
}
|
|
|
|
Level3 struct {
|
|
|
|
ID uint
|
|
|
|
Level2s []Level2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
DB.DropTableIfExists(&Level3{})
|
|
|
|
DB.DropTableIfExists(&Level2{})
|
|
|
|
DB.DropTableIfExists(&Level1{})
|
|
|
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := make([]Level3, 2)
|
|
|
|
want[0] = Level3{
|
|
|
|
Level2s: []Level2{
|
|
|
|
{
|
|
|
|
Level1s: []Level1{
|
|
|
|
{Value: "value1"},
|
|
|
|
{Value: "value2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Level1s: []Level1{
|
|
|
|
{Value: "value3"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want[0]).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
want[1] = Level3{
|
|
|
|
Level2s: []Level2{
|
|
|
|
{
|
|
|
|
Level1s: []Level1{
|
|
|
|
{Value: "value3"},
|
|
|
|
{Value: "value4"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Level1s: []Level1{
|
|
|
|
{Value: "value5"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want[1]).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var got []Level3
|
|
|
|
if err := DB.Preload("Level2s.Level1s").Find(&got).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
type (
|
|
|
|
Level1 struct {
|
|
|
|
ID uint
|
|
|
|
Value string
|
|
|
|
Level2ID uint
|
|
|
|
}
|
|
|
|
Level2 struct {
|
|
|
|
ID uint
|
|
|
|
Level1 Level1
|
|
|
|
Level3ID uint
|
|
|
|
}
|
|
|
|
Level3 struct {
|
|
|
|
ID uint
|
|
|
|
Level2s []Level2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
DB.DropTableIfExists(&Level3{})
|
|
|
|
DB.DropTableIfExists(&Level2{})
|
|
|
|
DB.DropTableIfExists(&Level1{})
|
|
|
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := make([]Level3, 2)
|
|
|
|
want[0] = Level3{
|
|
|
|
Level2s: []Level2{
|
|
|
|
{Level1: Level1{Value: "value1"}},
|
|
|
|
{Level1: Level1{Value: "value2"}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want[0]).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
want[1] = Level3{
|
|
|
|
Level2s: []Level2{
|
|
|
|
{Level1: Level1{Value: "value3"}},
|
|
|
|
{Level1: Level1{Value: "value4"}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want[1]).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var got []Level3
|
|
|
|
if err := DB.Preload("Level2s.Level1").Find(&got).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
type (
|
|
|
|
Level1 struct {
|
|
|
|
ID uint
|
|
|
|
Value string
|
|
|
|
Level2ID uint
|
|
|
|
}
|
|
|
|
Level2 struct {
|
|
|
|
ID uint
|
|
|
|
Level1s []Level1
|
|
|
|
Level3ID uint
|
|
|
|
}
|
|
|
|
Level3 struct {
|
|
|
|
ID uint
|
|
|
|
Level2 Level2
|
|
|
|
}
|
|
|
|
)
|
|
|
|
DB.DropTableIfExists(&Level3{})
|
|
|
|
DB.DropTableIfExists(&Level2{})
|
|
|
|
DB.DropTableIfExists(&Level1{})
|
|
|
|
if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
want := make([]Level3, 2)
|
|
|
|
want[0] = Level3{
|
|
|
|
Level2: Level2{
|
|
|
|
Level1s: []Level1{
|
|
|
|
Level1{Value: "value1"},
|
|
|
|
Level1{Value: "value2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want[0]).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
want[1] = Level3{
|
|
|
|
Level2: Level2{
|
|
|
|
Level1s: []Level1{
|
|
|
|
Level1{Value: "value3"},
|
|
|
|
Level1{Value: "value4"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := DB.Create(&want[1]).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var got []Level3
|
|
|
|
if err := DB.Preload("Level2.Level1s").Find(&got).Error; err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func toJSONString(v interface{}) []byte {
|
|
|
|
r, _ := json.MarshalIndent(v, "", " ")
|
|
|
|
return r
|
|
|
|
}
|