OSDN Git Service

Add db vendor (#45)
[bytom/vapor.git] / vendor / github.com / jinzhu / gorm / preload_test.go
1 package gorm_test
2
3 import (
4         "database/sql"
5         "encoding/json"
6         "os"
7         "reflect"
8         "testing"
9
10         "github.com/jinzhu/gorm"
11 )
12
13 func getPreloadUser(name string) *User {
14         return getPreparedUser(name, "Preload")
15 }
16
17 func checkUserHasPreloadData(user User, t *testing.T) {
18         u := getPreloadUser(user.Name)
19         if user.BillingAddress.Address1 != u.BillingAddress.Address1 {
20                 t.Error("Failed to preload user's BillingAddress")
21         }
22
23         if user.ShippingAddress.Address1 != u.ShippingAddress.Address1 {
24                 t.Error("Failed to preload user's ShippingAddress")
25         }
26
27         if user.CreditCard.Number != u.CreditCard.Number {
28                 t.Error("Failed to preload user's CreditCard")
29         }
30
31         if user.Company.Name != u.Company.Name {
32                 t.Error("Failed to preload user's Company")
33         }
34
35         if len(user.Emails) != len(u.Emails) {
36                 t.Error("Failed to preload user's Emails")
37         } else {
38                 var found int
39                 for _, e1 := range u.Emails {
40                         for _, e2 := range user.Emails {
41                                 if e1.Email == e2.Email {
42                                         found++
43                                         break
44                                 }
45                         }
46                 }
47                 if found != len(u.Emails) {
48                         t.Error("Failed to preload user's email details")
49                 }
50         }
51 }
52
53 func TestPreload(t *testing.T) {
54         user1 := getPreloadUser("user1")
55         DB.Save(user1)
56
57         preloadDB := DB.Where("role = ?", "Preload").Preload("BillingAddress").Preload("ShippingAddress").
58                 Preload("CreditCard").Preload("Emails").Preload("Company")
59         var user User
60         preloadDB.Find(&user)
61         checkUserHasPreloadData(user, t)
62
63         user2 := getPreloadUser("user2")
64         DB.Save(user2)
65
66         user3 := getPreloadUser("user3")
67         DB.Save(user3)
68
69         var users []User
70         preloadDB.Find(&users)
71
72         for _, user := range users {
73                 checkUserHasPreloadData(user, t)
74         }
75
76         var users2 []*User
77         preloadDB.Find(&users2)
78
79         for _, user := range users2 {
80                 checkUserHasPreloadData(*user, t)
81         }
82
83         var users3 []*User
84         preloadDB.Preload("Emails", "email = ?", user3.Emails[0].Email).Find(&users3)
85
86         for _, user := range users3 {
87                 if user.Name == user3.Name {
88                         if len(user.Emails) != 1 {
89                                 t.Errorf("should only preload one emails for user3 when with condition")
90                         }
91                 } else if len(user.Emails) != 0 {
92                         t.Errorf("should not preload any emails for other users when with condition")
93                 } else if user.Emails == nil {
94                         t.Errorf("should return an empty slice to indicate zero results")
95                 }
96         }
97 }
98
99 func TestAutoPreload(t *testing.T) {
100         user1 := getPreloadUser("auto_user1")
101         DB.Save(user1)
102
103         preloadDB := DB.Set("gorm:auto_preload", true).Where("role = ?", "Preload")
104         var user User
105         preloadDB.Find(&user)
106         checkUserHasPreloadData(user, t)
107
108         user2 := getPreloadUser("auto_user2")
109         DB.Save(user2)
110
111         var users []User
112         preloadDB.Find(&users)
113
114         for _, user := range users {
115                 checkUserHasPreloadData(user, t)
116         }
117
118         var users2 []*User
119         preloadDB.Find(&users2)
120
121         for _, user := range users2 {
122                 checkUserHasPreloadData(*user, t)
123         }
124 }
125
126 func TestAutoPreloadFalseDoesntPreload(t *testing.T) {
127         user1 := getPreloadUser("auto_user1")
128         DB.Save(user1)
129
130         preloadDB := DB.Set("gorm:auto_preload", false).Where("role = ?", "Preload")
131         var user User
132         preloadDB.Find(&user)
133
134         if user.BillingAddress.Address1 != "" {
135                 t.Error("AutoPreload was set to fasle, but still fetched data")
136         }
137
138         user2 := getPreloadUser("auto_user2")
139         DB.Save(user2)
140
141         var users []User
142         preloadDB.Find(&users)
143
144         for _, user := range users {
145                 if user.BillingAddress.Address1 != "" {
146                         t.Error("AutoPreload was set to fasle, but still fetched data")
147                 }
148         }
149 }
150
151 func TestNestedPreload1(t *testing.T) {
152         type (
153                 Level1 struct {
154                         ID       uint
155                         Value    string
156                         Level2ID uint
157                 }
158                 Level2 struct {
159                         ID       uint
160                         Level1   Level1
161                         Level3ID uint
162                 }
163                 Level3 struct {
164                         ID     uint
165                         Name   string
166                         Level2 Level2
167                 }
168         )
169         DB.DropTableIfExists(&Level3{})
170         DB.DropTableIfExists(&Level2{})
171         DB.DropTableIfExists(&Level1{})
172         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
173                 t.Error(err)
174         }
175
176         want := Level3{Level2: Level2{Level1: Level1{Value: "value"}}}
177         if err := DB.Create(&want).Error; err != nil {
178                 t.Error(err)
179         }
180
181         var got Level3
182         if err := DB.Preload("Level2").Preload("Level2.Level1").Find(&got).Error; err != nil {
183                 t.Error(err)
184         }
185
186         if !reflect.DeepEqual(got, want) {
187                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
188         }
189
190         if err := DB.Preload("Level2").Preload("Level2.Level1").Find(&got, "name = ?", "not_found").Error; err != gorm.ErrRecordNotFound {
191                 t.Error(err)
192         }
193 }
194
195 func TestNestedPreload2(t *testing.T) {
196         type (
197                 Level1 struct {
198                         ID       uint
199                         Value    string
200                         Level2ID uint
201                 }
202                 Level2 struct {
203                         ID       uint
204                         Level1s  []*Level1
205                         Level3ID uint
206                 }
207                 Level3 struct {
208                         ID      uint
209                         Name    string
210                         Level2s []Level2
211                 }
212         )
213         DB.DropTableIfExists(&Level3{})
214         DB.DropTableIfExists(&Level2{})
215         DB.DropTableIfExists(&Level1{})
216         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
217                 t.Error(err)
218         }
219
220         want := Level3{
221                 Level2s: []Level2{
222                         {
223                                 Level1s: []*Level1{
224                                         {Value: "value1"},
225                                         {Value: "value2"},
226                                 },
227                         },
228                         {
229                                 Level1s: []*Level1{
230                                         {Value: "value3"},
231                                 },
232                         },
233                 },
234         }
235         if err := DB.Create(&want).Error; err != nil {
236                 t.Error(err)
237         }
238
239         var got Level3
240         if err := DB.Preload("Level2s.Level1s").Find(&got).Error; err != nil {
241                 t.Error(err)
242         }
243
244         if !reflect.DeepEqual(got, want) {
245                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
246         }
247 }
248
249 func TestNestedPreload3(t *testing.T) {
250         type (
251                 Level1 struct {
252                         ID       uint
253                         Value    string
254                         Level2ID uint
255                 }
256                 Level2 struct {
257                         ID       uint
258                         Level1   Level1
259                         Level3ID uint
260                 }
261                 Level3 struct {
262                         Name    string
263                         ID      uint
264                         Level2s []Level2
265                 }
266         )
267         DB.DropTableIfExists(&Level3{})
268         DB.DropTableIfExists(&Level2{})
269         DB.DropTableIfExists(&Level1{})
270         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
271                 t.Error(err)
272         }
273
274         want := Level3{
275                 Level2s: []Level2{
276                         {Level1: Level1{Value: "value1"}},
277                         {Level1: Level1{Value: "value2"}},
278                 },
279         }
280         if err := DB.Create(&want).Error; err != nil {
281                 t.Error(err)
282         }
283
284         var got Level3
285         if err := DB.Preload("Level2s.Level1").Find(&got).Error; err != nil {
286                 t.Error(err)
287         }
288
289         if !reflect.DeepEqual(got, want) {
290                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
291         }
292 }
293
294 func TestNestedPreload4(t *testing.T) {
295         type (
296                 Level1 struct {
297                         ID       uint
298                         Value    string
299                         Level2ID uint
300                 }
301                 Level2 struct {
302                         ID       uint
303                         Level1s  []Level1
304                         Level3ID uint
305                 }
306                 Level3 struct {
307                         ID     uint
308                         Name   string
309                         Level2 Level2
310                 }
311         )
312         DB.DropTableIfExists(&Level3{})
313         DB.DropTableIfExists(&Level2{})
314         DB.DropTableIfExists(&Level1{})
315         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
316                 t.Error(err)
317         }
318
319         want := Level3{
320                 Level2: Level2{
321                         Level1s: []Level1{
322                                 {Value: "value1"},
323                                 {Value: "value2"},
324                         },
325                 },
326         }
327         if err := DB.Create(&want).Error; err != nil {
328                 t.Error(err)
329         }
330
331         var got Level3
332         if err := DB.Preload("Level2.Level1s").Find(&got).Error; err != nil {
333                 t.Error(err)
334         }
335
336         if !reflect.DeepEqual(got, want) {
337                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
338         }
339 }
340
341 // Slice: []Level3
342 func TestNestedPreload5(t *testing.T) {
343         type (
344                 Level1 struct {
345                         ID       uint
346                         Value    string
347                         Level2ID uint
348                 }
349                 Level2 struct {
350                         ID       uint
351                         Level1   Level1
352                         Level3ID uint
353                 }
354                 Level3 struct {
355                         ID     uint
356                         Name   string
357                         Level2 Level2
358                 }
359         )
360         DB.DropTableIfExists(&Level3{})
361         DB.DropTableIfExists(&Level2{})
362         DB.DropTableIfExists(&Level1{})
363         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
364                 t.Error(err)
365         }
366
367         want := make([]Level3, 2)
368         want[0] = Level3{Level2: Level2{Level1: Level1{Value: "value"}}}
369         if err := DB.Create(&want[0]).Error; err != nil {
370                 t.Error(err)
371         }
372         want[1] = Level3{Level2: Level2{Level1: Level1{Value: "value2"}}}
373         if err := DB.Create(&want[1]).Error; err != nil {
374                 t.Error(err)
375         }
376
377         var got []Level3
378         if err := DB.Preload("Level2").Preload("Level2.Level1").Find(&got).Error; err != nil {
379                 t.Error(err)
380         }
381
382         if !reflect.DeepEqual(got, want) {
383                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
384         }
385 }
386
387 func TestNestedPreload6(t *testing.T) {
388         type (
389                 Level1 struct {
390                         ID       uint
391                         Value    string
392                         Level2ID uint
393                 }
394                 Level2 struct {
395                         ID       uint
396                         Level1s  []Level1
397                         Level3ID uint
398                 }
399                 Level3 struct {
400                         ID      uint
401                         Name    string
402                         Level2s []Level2
403                 }
404         )
405         DB.DropTableIfExists(&Level3{})
406         DB.DropTableIfExists(&Level2{})
407         DB.DropTableIfExists(&Level1{})
408         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
409                 t.Error(err)
410         }
411
412         want := make([]Level3, 2)
413         want[0] = Level3{
414                 Level2s: []Level2{
415                         {
416                                 Level1s: []Level1{
417                                         {Value: "value1"},
418                                         {Value: "value2"},
419                                 },
420                         },
421                         {
422                                 Level1s: []Level1{
423                                         {Value: "value3"},
424                                 },
425                         },
426                 },
427         }
428         if err := DB.Create(&want[0]).Error; err != nil {
429                 t.Error(err)
430         }
431
432         want[1] = Level3{
433                 Level2s: []Level2{
434                         {
435                                 Level1s: []Level1{
436                                         {Value: "value3"},
437                                         {Value: "value4"},
438                                 },
439                         },
440                         {
441                                 Level1s: []Level1{
442                                         {Value: "value5"},
443                                 },
444                         },
445                 },
446         }
447         if err := DB.Create(&want[1]).Error; err != nil {
448                 t.Error(err)
449         }
450
451         var got []Level3
452         if err := DB.Preload("Level2s.Level1s").Find(&got).Error; err != nil {
453                 t.Error(err)
454         }
455
456         if !reflect.DeepEqual(got, want) {
457                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
458         }
459 }
460
461 func TestNestedPreload7(t *testing.T) {
462         type (
463                 Level1 struct {
464                         ID       uint
465                         Value    string
466                         Level2ID uint
467                 }
468                 Level2 struct {
469                         ID       uint
470                         Level1   Level1
471                         Level3ID uint
472                 }
473                 Level3 struct {
474                         ID      uint
475                         Name    string
476                         Level2s []Level2
477                 }
478         )
479         DB.DropTableIfExists(&Level3{})
480         DB.DropTableIfExists(&Level2{})
481         DB.DropTableIfExists(&Level1{})
482         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
483                 t.Error(err)
484         }
485
486         want := make([]Level3, 2)
487         want[0] = Level3{
488                 Level2s: []Level2{
489                         {Level1: Level1{Value: "value1"}},
490                         {Level1: Level1{Value: "value2"}},
491                 },
492         }
493         if err := DB.Create(&want[0]).Error; err != nil {
494                 t.Error(err)
495         }
496
497         want[1] = Level3{
498                 Level2s: []Level2{
499                         {Level1: Level1{Value: "value3"}},
500                         {Level1: Level1{Value: "value4"}},
501                 },
502         }
503         if err := DB.Create(&want[1]).Error; err != nil {
504                 t.Error(err)
505         }
506
507         var got []Level3
508         if err := DB.Preload("Level2s.Level1").Find(&got).Error; err != nil {
509                 t.Error(err)
510         }
511
512         if !reflect.DeepEqual(got, want) {
513                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
514         }
515 }
516
517 func TestNestedPreload8(t *testing.T) {
518         type (
519                 Level1 struct {
520                         ID       uint
521                         Value    string
522                         Level2ID uint
523                 }
524                 Level2 struct {
525                         ID       uint
526                         Level1s  []Level1
527                         Level3ID uint
528                 }
529                 Level3 struct {
530                         ID     uint
531                         Name   string
532                         Level2 Level2
533                 }
534         )
535         DB.DropTableIfExists(&Level3{})
536         DB.DropTableIfExists(&Level2{})
537         DB.DropTableIfExists(&Level1{})
538         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
539                 t.Error(err)
540         }
541
542         want := make([]Level3, 2)
543         want[0] = Level3{
544                 Level2: Level2{
545                         Level1s: []Level1{
546                                 {Value: "value1"},
547                                 {Value: "value2"},
548                         },
549                 },
550         }
551         if err := DB.Create(&want[0]).Error; err != nil {
552                 t.Error(err)
553         }
554         want[1] = Level3{
555                 Level2: Level2{
556                         Level1s: []Level1{
557                                 {Value: "value3"},
558                                 {Value: "value4"},
559                         },
560                 },
561         }
562         if err := DB.Create(&want[1]).Error; err != nil {
563                 t.Error(err)
564         }
565
566         var got []Level3
567         if err := DB.Preload("Level2.Level1s").Find(&got).Error; err != nil {
568                 t.Error(err)
569         }
570
571         if !reflect.DeepEqual(got, want) {
572                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
573         }
574 }
575
576 func TestNestedPreload9(t *testing.T) {
577         type (
578                 Level0 struct {
579                         ID       uint
580                         Value    string
581                         Level1ID uint
582                 }
583                 Level1 struct {
584                         ID         uint
585                         Value      string
586                         Level2ID   uint
587                         Level2_1ID uint
588                         Level0s    []Level0
589                 }
590                 Level2 struct {
591                         ID       uint
592                         Level1s  []Level1
593                         Level3ID uint
594                 }
595                 Level2_1 struct {
596                         ID       uint
597                         Level1s  []Level1
598                         Level3ID uint
599                 }
600                 Level3 struct {
601                         ID       uint
602                         Name     string
603                         Level2   Level2
604                         Level2_1 Level2_1
605                 }
606         )
607         DB.DropTableIfExists(&Level3{})
608         DB.DropTableIfExists(&Level2{})
609         DB.DropTableIfExists(&Level2_1{})
610         DB.DropTableIfExists(&Level1{})
611         DB.DropTableIfExists(&Level0{})
612         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}, &Level2_1{}, &Level0{}).Error; err != nil {
613                 t.Error(err)
614         }
615
616         want := make([]Level3, 2)
617         want[0] = Level3{
618                 Level2: Level2{
619                         Level1s: []Level1{
620                                 {Value: "value1"},
621                                 {Value: "value2"},
622                         },
623                 },
624                 Level2_1: Level2_1{
625                         Level1s: []Level1{
626                                 {
627                                         Value:   "value1-1",
628                                         Level0s: []Level0{{Value: "Level0-1"}},
629                                 },
630                                 {
631                                         Value:   "value2-2",
632                                         Level0s: []Level0{{Value: "Level0-2"}},
633                                 },
634                         },
635                 },
636         }
637         if err := DB.Create(&want[0]).Error; err != nil {
638                 t.Error(err)
639         }
640         want[1] = Level3{
641                 Level2: Level2{
642                         Level1s: []Level1{
643                                 {Value: "value3"},
644                                 {Value: "value4"},
645                         },
646                 },
647                 Level2_1: Level2_1{
648                         Level1s: []Level1{
649                                 {
650                                         Value:   "value3-3",
651                                         Level0s: []Level0{},
652                                 },
653                                 {
654                                         Value:   "value4-4",
655                                         Level0s: []Level0{},
656                                 },
657                         },
658                 },
659         }
660         if err := DB.Create(&want[1]).Error; err != nil {
661                 t.Error(err)
662         }
663
664         var got []Level3
665         if err := DB.Preload("Level2").Preload("Level2.Level1s").Preload("Level2_1").Preload("Level2_1.Level1s").Preload("Level2_1.Level1s.Level0s").Find(&got).Error; err != nil {
666                 t.Error(err)
667         }
668
669         if !reflect.DeepEqual(got, want) {
670                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
671         }
672 }
673
674 type LevelA1 struct {
675         ID    uint
676         Value string
677 }
678
679 type LevelA2 struct {
680         ID       uint
681         Value    string
682         LevelA3s []*LevelA3
683 }
684
685 type LevelA3 struct {
686         ID        uint
687         Value     string
688         LevelA1ID sql.NullInt64
689         LevelA1   *LevelA1
690         LevelA2ID sql.NullInt64
691         LevelA2   *LevelA2
692 }
693
694 func TestNestedPreload10(t *testing.T) {
695         DB.DropTableIfExists(&LevelA3{})
696         DB.DropTableIfExists(&LevelA2{})
697         DB.DropTableIfExists(&LevelA1{})
698
699         if err := DB.AutoMigrate(&LevelA1{}, &LevelA2{}, &LevelA3{}).Error; err != nil {
700                 t.Error(err)
701         }
702
703         levelA1 := &LevelA1{Value: "foo"}
704         if err := DB.Save(levelA1).Error; err != nil {
705                 t.Error(err)
706         }
707
708         want := []*LevelA2{
709                 {
710                         Value: "bar",
711                         LevelA3s: []*LevelA3{
712                                 {
713                                         Value:   "qux",
714                                         LevelA1: levelA1,
715                                 },
716                         },
717                 },
718                 {
719                         Value:    "bar 2",
720                         LevelA3s: []*LevelA3{},
721                 },
722         }
723         for _, levelA2 := range want {
724                 if err := DB.Save(levelA2).Error; err != nil {
725                         t.Error(err)
726                 }
727         }
728
729         var got []*LevelA2
730         if err := DB.Preload("LevelA3s.LevelA1").Find(&got).Error; err != nil {
731                 t.Error(err)
732         }
733
734         if !reflect.DeepEqual(got, want) {
735                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
736         }
737 }
738
739 type LevelB1 struct {
740         ID       uint
741         Value    string
742         LevelB3s []*LevelB3
743 }
744
745 type LevelB2 struct {
746         ID    uint
747         Value string
748 }
749
750 type LevelB3 struct {
751         ID        uint
752         Value     string
753         LevelB1ID sql.NullInt64
754         LevelB1   *LevelB1
755         LevelB2s  []*LevelB2 `gorm:"many2many:levelb1_levelb3_levelb2s"`
756 }
757
758 func TestNestedPreload11(t *testing.T) {
759         DB.DropTableIfExists(&LevelB2{})
760         DB.DropTableIfExists(&LevelB3{})
761         DB.DropTableIfExists(&LevelB1{})
762         if err := DB.AutoMigrate(&LevelB1{}, &LevelB2{}, &LevelB3{}).Error; err != nil {
763                 t.Error(err)
764         }
765
766         levelB1 := &LevelB1{Value: "foo"}
767         if err := DB.Create(levelB1).Error; err != nil {
768                 t.Error(err)
769         }
770
771         levelB3 := &LevelB3{
772                 Value:     "bar",
773                 LevelB1ID: sql.NullInt64{Valid: true, Int64: int64(levelB1.ID)},
774         }
775         if err := DB.Create(levelB3).Error; err != nil {
776                 t.Error(err)
777         }
778         levelB1.LevelB3s = []*LevelB3{levelB3}
779
780         want := []*LevelB1{levelB1}
781         var got []*LevelB1
782         if err := DB.Preload("LevelB3s.LevelB2s").Find(&got).Error; err != nil {
783                 t.Error(err)
784         }
785
786         if !reflect.DeepEqual(got, want) {
787                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
788         }
789 }
790
791 type LevelC1 struct {
792         ID        uint
793         Value     string
794         LevelC2ID uint
795 }
796
797 type LevelC2 struct {
798         ID      uint
799         Value   string
800         LevelC1 LevelC1
801 }
802
803 type LevelC3 struct {
804         ID        uint
805         Value     string
806         LevelC2ID uint
807         LevelC2   LevelC2
808 }
809
810 func TestNestedPreload12(t *testing.T) {
811         DB.DropTableIfExists(&LevelC2{})
812         DB.DropTableIfExists(&LevelC3{})
813         DB.DropTableIfExists(&LevelC1{})
814         if err := DB.AutoMigrate(&LevelC1{}, &LevelC2{}, &LevelC3{}).Error; err != nil {
815                 t.Error(err)
816         }
817
818         level2 := LevelC2{
819                 Value: "c2",
820                 LevelC1: LevelC1{
821                         Value: "c1",
822                 },
823         }
824         DB.Create(&level2)
825
826         want := []LevelC3{
827                 {
828                         Value:   "c3-1",
829                         LevelC2: level2,
830                 }, {
831                         Value:   "c3-2",
832                         LevelC2: level2,
833                 },
834         }
835
836         for i := range want {
837                 if err := DB.Create(&want[i]).Error; err != nil {
838                         t.Error(err)
839                 }
840         }
841
842         var got []LevelC3
843         if err := DB.Preload("LevelC2").Preload("LevelC2.LevelC1").Find(&got).Error; err != nil {
844                 t.Error(err)
845         }
846
847         if !reflect.DeepEqual(got, want) {
848                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
849         }
850 }
851
852 func TestManyToManyPreloadWithMultiPrimaryKeys(t *testing.T) {
853         if dialect := os.Getenv("GORM_DIALECT"); dialect == "" || dialect == "sqlite" || dialect == "mssql" {
854                 return
855         }
856
857         type (
858                 Level1 struct {
859                         ID           uint   `gorm:"primary_key;"`
860                         LanguageCode string `gorm:"primary_key"`
861                         Value        string
862                 }
863                 Level2 struct {
864                         ID           uint   `gorm:"primary_key;"`
865                         LanguageCode string `gorm:"primary_key"`
866                         Value        string
867                         Level1s      []Level1 `gorm:"many2many:levels;"`
868                 }
869         )
870
871         DB.DropTableIfExists(&Level2{})
872         DB.DropTableIfExists(&Level1{})
873         DB.DropTableIfExists("levels")
874
875         if err := DB.AutoMigrate(&Level2{}, &Level1{}).Error; err != nil {
876                 t.Error(err)
877         }
878
879         want := Level2{Value: "Bob", LanguageCode: "ru", Level1s: []Level1{
880                 {Value: "ru", LanguageCode: "ru"},
881                 {Value: "en", LanguageCode: "en"},
882         }}
883         if err := DB.Save(&want).Error; err != nil {
884                 t.Error(err)
885         }
886
887         want2 := Level2{Value: "Tom", LanguageCode: "zh", Level1s: []Level1{
888                 {Value: "zh", LanguageCode: "zh"},
889                 {Value: "de", LanguageCode: "de"},
890         }}
891         if err := DB.Save(&want2).Error; err != nil {
892                 t.Error(err)
893         }
894
895         var got Level2
896         if err := DB.Preload("Level1s").Find(&got, "value = ?", "Bob").Error; err != nil {
897                 t.Error(err)
898         }
899
900         if !reflect.DeepEqual(got, want) {
901                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
902         }
903
904         var got2 Level2
905         if err := DB.Preload("Level1s").Find(&got2, "value = ?", "Tom").Error; err != nil {
906                 t.Error(err)
907         }
908
909         if !reflect.DeepEqual(got2, want2) {
910                 t.Errorf("got %s; want %s", toJSONString(got2), toJSONString(want2))
911         }
912
913         var got3 []Level2
914         if err := DB.Preload("Level1s").Find(&got3, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil {
915                 t.Error(err)
916         }
917
918         if !reflect.DeepEqual(got3, []Level2{got, got2}) {
919                 t.Errorf("got %s; want %s", toJSONString(got3), toJSONString([]Level2{got, got2}))
920         }
921
922         var got4 []Level2
923         if err := DB.Preload("Level1s", "value IN (?)", []string{"zh", "ru"}).Find(&got4, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil {
924                 t.Error(err)
925         }
926
927         var ruLevel1 Level1
928         var zhLevel1 Level1
929         DB.First(&ruLevel1, "value = ?", "ru")
930         DB.First(&zhLevel1, "value = ?", "zh")
931
932         got.Level1s = []Level1{ruLevel1}
933         got2.Level1s = []Level1{zhLevel1}
934         if !reflect.DeepEqual(got4, []Level2{got, got2}) {
935                 t.Errorf("got %s; want %s", toJSONString(got4), toJSONString([]Level2{got, got2}))
936         }
937
938         if err := DB.Preload("Level1s").Find(&got4, "value IN (?)", []string{"non-existing"}).Error; err != nil {
939                 t.Error(err)
940         }
941 }
942
943 func TestManyToManyPreloadForNestedPointer(t *testing.T) {
944         type (
945                 Level1 struct {
946                         ID    uint
947                         Value string
948                 }
949                 Level2 struct {
950                         ID      uint
951                         Value   string
952                         Level1s []*Level1 `gorm:"many2many:levels;"`
953                 }
954                 Level3 struct {
955                         ID       uint
956                         Value    string
957                         Level2ID sql.NullInt64
958                         Level2   *Level2
959                 }
960         )
961
962         DB.DropTableIfExists(&Level3{})
963         DB.DropTableIfExists(&Level2{})
964         DB.DropTableIfExists(&Level1{})
965         DB.DropTableIfExists("levels")
966
967         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
968                 t.Error(err)
969         }
970
971         want := Level3{
972                 Value: "Bob",
973                 Level2: &Level2{
974                         Value: "Foo",
975                         Level1s: []*Level1{
976                                 {Value: "ru"},
977                                 {Value: "en"},
978                         },
979                 },
980         }
981         if err := DB.Save(&want).Error; err != nil {
982                 t.Error(err)
983         }
984
985         want2 := Level3{
986                 Value: "Tom",
987                 Level2: &Level2{
988                         Value: "Bar",
989                         Level1s: []*Level1{
990                                 {Value: "zh"},
991                                 {Value: "de"},
992                         },
993                 },
994         }
995         if err := DB.Save(&want2).Error; err != nil {
996                 t.Error(err)
997         }
998
999         var got Level3
1000         if err := DB.Preload("Level2.Level1s").Find(&got, "value = ?", "Bob").Error; err != nil {
1001                 t.Error(err)
1002         }
1003
1004         if !reflect.DeepEqual(got, want) {
1005                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
1006         }
1007
1008         var got2 Level3
1009         if err := DB.Preload("Level2.Level1s").Find(&got2, "value = ?", "Tom").Error; err != nil {
1010                 t.Error(err)
1011         }
1012
1013         if !reflect.DeepEqual(got2, want2) {
1014                 t.Errorf("got %s; want %s", toJSONString(got2), toJSONString(want2))
1015         }
1016
1017         var got3 []Level3
1018         if err := DB.Preload("Level2.Level1s").Find(&got3, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil {
1019                 t.Error(err)
1020         }
1021
1022         if !reflect.DeepEqual(got3, []Level3{got, got2}) {
1023                 t.Errorf("got %s; want %s", toJSONString(got3), toJSONString([]Level3{got, got2}))
1024         }
1025
1026         var got4 []Level3
1027         if err := DB.Preload("Level2.Level1s", "value IN (?)", []string{"zh", "ru"}).Find(&got4, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil {
1028                 t.Error(err)
1029         }
1030
1031         var got5 Level3
1032         DB.Preload("Level2.Level1s").Find(&got5, "value = ?", "bogus")
1033
1034         var ruLevel1 Level1
1035         var zhLevel1 Level1
1036         DB.First(&ruLevel1, "value = ?", "ru")
1037         DB.First(&zhLevel1, "value = ?", "zh")
1038
1039         got.Level2.Level1s = []*Level1{&ruLevel1}
1040         got2.Level2.Level1s = []*Level1{&zhLevel1}
1041         if !reflect.DeepEqual(got4, []Level3{got, got2}) {
1042                 t.Errorf("got %s; want %s", toJSONString(got4), toJSONString([]Level3{got, got2}))
1043         }
1044 }
1045
1046 func TestNestedManyToManyPreload(t *testing.T) {
1047         type (
1048                 Level1 struct {
1049                         ID    uint
1050                         Value string
1051                 }
1052                 Level2 struct {
1053                         ID      uint
1054                         Value   string
1055                         Level1s []*Level1 `gorm:"many2many:level1_level2;"`
1056                 }
1057                 Level3 struct {
1058                         ID      uint
1059                         Value   string
1060                         Level2s []Level2 `gorm:"many2many:level2_level3;"`
1061                 }
1062         )
1063
1064         DB.DropTableIfExists(&Level1{})
1065         DB.DropTableIfExists(&Level2{})
1066         DB.DropTableIfExists(&Level3{})
1067         DB.DropTableIfExists("level1_level2")
1068         DB.DropTableIfExists("level2_level3")
1069
1070         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
1071                 t.Error(err)
1072         }
1073
1074         want := Level3{
1075                 Value: "Level3",
1076                 Level2s: []Level2{
1077                         {
1078                                 Value: "Bob",
1079                                 Level1s: []*Level1{
1080                                         {Value: "ru"},
1081                                         {Value: "en"},
1082                                 },
1083                         }, {
1084                                 Value: "Tom",
1085                                 Level1s: []*Level1{
1086                                         {Value: "zh"},
1087                                         {Value: "de"},
1088                                 },
1089                         },
1090                 },
1091         }
1092
1093         if err := DB.Save(&want).Error; err != nil {
1094                 t.Error(err)
1095         }
1096
1097         var got Level3
1098         if err := DB.Preload("Level2s").Preload("Level2s.Level1s").Find(&got, "value = ?", "Level3").Error; err != nil {
1099                 t.Error(err)
1100         }
1101
1102         if !reflect.DeepEqual(got, want) {
1103                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
1104         }
1105
1106         if err := DB.Preload("Level2s.Level1s").Find(&got, "value = ?", "not_found").Error; err != gorm.ErrRecordNotFound {
1107                 t.Error(err)
1108         }
1109 }
1110
1111 func TestNestedManyToManyPreload2(t *testing.T) {
1112         type (
1113                 Level1 struct {
1114                         ID    uint
1115                         Value string
1116                 }
1117                 Level2 struct {
1118                         ID      uint
1119                         Value   string
1120                         Level1s []*Level1 `gorm:"many2many:level1_level2;"`
1121                 }
1122                 Level3 struct {
1123                         ID       uint
1124                         Value    string
1125                         Level2ID sql.NullInt64
1126                         Level2   *Level2
1127                 }
1128         )
1129
1130         DB.DropTableIfExists(&Level1{})
1131         DB.DropTableIfExists(&Level2{})
1132         DB.DropTableIfExists(&Level3{})
1133         DB.DropTableIfExists("level1_level2")
1134
1135         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
1136                 t.Error(err)
1137         }
1138
1139         want := Level3{
1140                 Value: "Level3",
1141                 Level2: &Level2{
1142                         Value: "Bob",
1143                         Level1s: []*Level1{
1144                                 {Value: "ru"},
1145                                 {Value: "en"},
1146                         },
1147                 },
1148         }
1149
1150         if err := DB.Save(&want).Error; err != nil {
1151                 t.Error(err)
1152         }
1153
1154         var got Level3
1155         if err := DB.Preload("Level2.Level1s").Find(&got, "value = ?", "Level3").Error; err != nil {
1156                 t.Error(err)
1157         }
1158
1159         if !reflect.DeepEqual(got, want) {
1160                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
1161         }
1162
1163         if err := DB.Preload("Level2.Level1s").Find(&got, "value = ?", "not_found").Error; err != gorm.ErrRecordNotFound {
1164                 t.Error(err)
1165         }
1166 }
1167
1168 func TestNestedManyToManyPreload3(t *testing.T) {
1169         type (
1170                 Level1 struct {
1171                         ID    uint
1172                         Value string
1173                 }
1174                 Level2 struct {
1175                         ID      uint
1176                         Value   string
1177                         Level1s []*Level1 `gorm:"many2many:level1_level2;"`
1178                 }
1179                 Level3 struct {
1180                         ID       uint
1181                         Value    string
1182                         Level2ID sql.NullInt64
1183                         Level2   *Level2
1184                 }
1185         )
1186
1187         DB.DropTableIfExists(&Level1{})
1188         DB.DropTableIfExists(&Level2{})
1189         DB.DropTableIfExists(&Level3{})
1190         DB.DropTableIfExists("level1_level2")
1191
1192         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
1193                 t.Error(err)
1194         }
1195
1196         level1Zh := &Level1{Value: "zh"}
1197         level1Ru := &Level1{Value: "ru"}
1198         level1En := &Level1{Value: "en"}
1199
1200         level21 := &Level2{
1201                 Value:   "Level2-1",
1202                 Level1s: []*Level1{level1Zh, level1Ru},
1203         }
1204
1205         level22 := &Level2{
1206                 Value:   "Level2-2",
1207                 Level1s: []*Level1{level1Zh, level1En},
1208         }
1209
1210         wants := []*Level3{
1211                 {
1212                         Value:  "Level3-1",
1213                         Level2: level21,
1214                 },
1215                 {
1216                         Value:  "Level3-2",
1217                         Level2: level22,
1218                 },
1219                 {
1220                         Value:  "Level3-3",
1221                         Level2: level21,
1222                 },
1223         }
1224
1225         for _, want := range wants {
1226                 if err := DB.Save(&want).Error; err != nil {
1227                         t.Error(err)
1228                 }
1229         }
1230
1231         var gots []*Level3
1232         if err := DB.Preload("Level2.Level1s", func(db *gorm.DB) *gorm.DB {
1233                 return db.Order("level1.id ASC")
1234         }).Find(&gots).Error; err != nil {
1235                 t.Error(err)
1236         }
1237
1238         if !reflect.DeepEqual(gots, wants) {
1239                 t.Errorf("got %s; want %s", toJSONString(gots), toJSONString(wants))
1240         }
1241 }
1242
1243 func TestNestedManyToManyPreload3ForStruct(t *testing.T) {
1244         type (
1245                 Level1 struct {
1246                         ID    uint
1247                         Value string
1248                 }
1249                 Level2 struct {
1250                         ID      uint
1251                         Value   string
1252                         Level1s []Level1 `gorm:"many2many:level1_level2;"`
1253                 }
1254                 Level3 struct {
1255                         ID       uint
1256                         Value    string
1257                         Level2ID sql.NullInt64
1258                         Level2   Level2
1259                 }
1260         )
1261
1262         DB.DropTableIfExists(&Level1{})
1263         DB.DropTableIfExists(&Level2{})
1264         DB.DropTableIfExists(&Level3{})
1265         DB.DropTableIfExists("level1_level2")
1266
1267         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
1268                 t.Error(err)
1269         }
1270
1271         level1Zh := Level1{Value: "zh"}
1272         level1Ru := Level1{Value: "ru"}
1273         level1En := Level1{Value: "en"}
1274
1275         level21 := Level2{
1276                 Value:   "Level2-1",
1277                 Level1s: []Level1{level1Zh, level1Ru},
1278         }
1279
1280         level22 := Level2{
1281                 Value:   "Level2-2",
1282                 Level1s: []Level1{level1Zh, level1En},
1283         }
1284
1285         wants := []*Level3{
1286                 {
1287                         Value:  "Level3-1",
1288                         Level2: level21,
1289                 },
1290                 {
1291                         Value:  "Level3-2",
1292                         Level2: level22,
1293                 },
1294                 {
1295                         Value:  "Level3-3",
1296                         Level2: level21,
1297                 },
1298         }
1299
1300         for _, want := range wants {
1301                 if err := DB.Save(&want).Error; err != nil {
1302                         t.Error(err)
1303                 }
1304         }
1305
1306         var gots []*Level3
1307         if err := DB.Preload("Level2.Level1s", func(db *gorm.DB) *gorm.DB {
1308                 return db.Order("level1.id ASC")
1309         }).Find(&gots).Error; err != nil {
1310                 t.Error(err)
1311         }
1312
1313         if !reflect.DeepEqual(gots, wants) {
1314                 t.Errorf("got %s; want %s", toJSONString(gots), toJSONString(wants))
1315         }
1316 }
1317
1318 func TestNestedManyToManyPreload4(t *testing.T) {
1319         type (
1320                 Level4 struct {
1321                         ID       uint
1322                         Value    string
1323                         Level3ID uint
1324                 }
1325                 Level3 struct {
1326                         ID      uint
1327                         Value   string
1328                         Level4s []*Level4
1329                 }
1330                 Level2 struct {
1331                         ID      uint
1332                         Value   string
1333                         Level3s []*Level3 `gorm:"many2many:level2_level3;"`
1334                 }
1335                 Level1 struct {
1336                         ID      uint
1337                         Value   string
1338                         Level2s []*Level2 `gorm:"many2many:level1_level2;"`
1339                 }
1340         )
1341
1342         DB.DropTableIfExists(&Level1{})
1343         DB.DropTableIfExists(&Level2{})
1344         DB.DropTableIfExists(&Level3{})
1345         DB.DropTableIfExists(&Level4{})
1346         DB.DropTableIfExists("level1_level2")
1347         DB.DropTableIfExists("level2_level3")
1348
1349         dummy := Level1{
1350                 Value: "Level1",
1351                 Level2s: []*Level2{{
1352                         Value: "Level2",
1353                         Level3s: []*Level3{{
1354                                 Value: "Level3",
1355                                 Level4s: []*Level4{{
1356                                         Value: "Level4",
1357                                 }},
1358                         }},
1359                 }},
1360         }
1361
1362         if err := DB.AutoMigrate(&Level4{}, &Level3{}, &Level2{}, &Level1{}).Error; err != nil {
1363                 t.Error(err)
1364         }
1365
1366         if err := DB.Save(&dummy).Error; err != nil {
1367                 t.Error(err)
1368         }
1369
1370         var level1 Level1
1371         if err := DB.Preload("Level2s").Preload("Level2s.Level3s").Preload("Level2s.Level3s.Level4s").First(&level1).Error; err != nil {
1372                 t.Error(err)
1373         }
1374 }
1375
1376 func TestManyToManyPreloadForPointer(t *testing.T) {
1377         type (
1378                 Level1 struct {
1379                         ID    uint
1380                         Value string
1381                 }
1382                 Level2 struct {
1383                         ID      uint
1384                         Value   string
1385                         Level1s []*Level1 `gorm:"many2many:levels;"`
1386                 }
1387         )
1388
1389         DB.DropTableIfExists(&Level2{})
1390         DB.DropTableIfExists(&Level1{})
1391         DB.DropTableIfExists("levels")
1392
1393         if err := DB.AutoMigrate(&Level2{}, &Level1{}).Error; err != nil {
1394                 t.Error(err)
1395         }
1396
1397         want := Level2{Value: "Bob", Level1s: []*Level1{
1398                 {Value: "ru"},
1399                 {Value: "en"},
1400         }}
1401         if err := DB.Save(&want).Error; err != nil {
1402                 t.Error(err)
1403         }
1404
1405         want2 := Level2{Value: "Tom", Level1s: []*Level1{
1406                 {Value: "zh"},
1407                 {Value: "de"},
1408         }}
1409         if err := DB.Save(&want2).Error; err != nil {
1410                 t.Error(err)
1411         }
1412
1413         var got Level2
1414         if err := DB.Preload("Level1s").Find(&got, "value = ?", "Bob").Error; err != nil {
1415                 t.Error(err)
1416         }
1417
1418         if !reflect.DeepEqual(got, want) {
1419                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
1420         }
1421
1422         var got2 Level2
1423         if err := DB.Preload("Level1s").Find(&got2, "value = ?", "Tom").Error; err != nil {
1424                 t.Error(err)
1425         }
1426
1427         if !reflect.DeepEqual(got2, want2) {
1428                 t.Errorf("got %s; want %s", toJSONString(got2), toJSONString(want2))
1429         }
1430
1431         var got3 []Level2
1432         if err := DB.Preload("Level1s").Find(&got3, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil {
1433                 t.Error(err)
1434         }
1435
1436         if !reflect.DeepEqual(got3, []Level2{got, got2}) {
1437                 t.Errorf("got %s; want %s", toJSONString(got3), toJSONString([]Level2{got, got2}))
1438         }
1439
1440         var got4 []Level2
1441         if err := DB.Preload("Level1s", "value IN (?)", []string{"zh", "ru"}).Find(&got4, "value IN (?)", []string{"Bob", "Tom"}).Error; err != nil {
1442                 t.Error(err)
1443         }
1444
1445         var got5 Level2
1446         DB.Preload("Level1s").First(&got5, "value = ?", "bogus")
1447
1448         var ruLevel1 Level1
1449         var zhLevel1 Level1
1450         DB.First(&ruLevel1, "value = ?", "ru")
1451         DB.First(&zhLevel1, "value = ?", "zh")
1452
1453         got.Level1s = []*Level1{&ruLevel1}
1454         got2.Level1s = []*Level1{&zhLevel1}
1455         if !reflect.DeepEqual(got4, []Level2{got, got2}) {
1456                 t.Errorf("got %s; want %s", toJSONString(got4), toJSONString([]Level2{got, got2}))
1457         }
1458 }
1459
1460 func TestNilPointerSlice(t *testing.T) {
1461         type (
1462                 Level3 struct {
1463                         ID    uint
1464                         Value string
1465                 }
1466                 Level2 struct {
1467                         ID       uint
1468                         Value    string
1469                         Level3ID uint
1470                         Level3   *Level3
1471                 }
1472                 Level1 struct {
1473                         ID       uint
1474                         Value    string
1475                         Level2ID uint
1476                         Level2   *Level2
1477                 }
1478         )
1479
1480         DB.DropTableIfExists(&Level3{})
1481         DB.DropTableIfExists(&Level2{})
1482         DB.DropTableIfExists(&Level1{})
1483
1484         if err := DB.AutoMigrate(&Level3{}, &Level2{}, &Level1{}).Error; err != nil {
1485                 t.Error(err)
1486         }
1487
1488         want := Level1{
1489                 Value: "Bob",
1490                 Level2: &Level2{
1491                         Value: "en",
1492                         Level3: &Level3{
1493                                 Value: "native",
1494                         },
1495                 },
1496         }
1497         if err := DB.Save(&want).Error; err != nil {
1498                 t.Error(err)
1499         }
1500
1501         want2 := Level1{
1502                 Value:  "Tom",
1503                 Level2: nil,
1504         }
1505         if err := DB.Save(&want2).Error; err != nil {
1506                 t.Error(err)
1507         }
1508
1509         var got []Level1
1510         if err := DB.Preload("Level2").Preload("Level2.Level3").Find(&got).Error; err != nil {
1511                 t.Error(err)
1512         }
1513
1514         if len(got) != 2 {
1515                 t.Errorf("got %v items, expected 2", len(got))
1516         }
1517
1518         if !reflect.DeepEqual(got[0], want) && !reflect.DeepEqual(got[1], want) {
1519                 t.Errorf("got %s; want array containing %s", toJSONString(got), toJSONString(want))
1520         }
1521
1522         if !reflect.DeepEqual(got[0], want2) && !reflect.DeepEqual(got[1], want2) {
1523                 t.Errorf("got %s; want array containing %s", toJSONString(got), toJSONString(want2))
1524         }
1525 }
1526
1527 func TestNilPointerSlice2(t *testing.T) {
1528         type (
1529                 Level4 struct {
1530                         ID uint
1531                 }
1532                 Level3 struct {
1533                         ID       uint
1534                         Level4ID sql.NullInt64 `sql:"index"`
1535                         Level4   *Level4
1536                 }
1537                 Level2 struct {
1538                         ID      uint
1539                         Level3s []*Level3 `gorm:"many2many:level2_level3s"`
1540                 }
1541                 Level1 struct {
1542                         ID       uint
1543                         Level2ID sql.NullInt64 `sql:"index"`
1544                         Level2   *Level2
1545                 }
1546         )
1547
1548         DB.DropTableIfExists(new(Level4))
1549         DB.DropTableIfExists(new(Level3))
1550         DB.DropTableIfExists(new(Level2))
1551         DB.DropTableIfExists(new(Level1))
1552
1553         if err := DB.AutoMigrate(new(Level4), new(Level3), new(Level2), new(Level1)).Error; err != nil {
1554                 t.Error(err)
1555         }
1556
1557         want := new(Level1)
1558         if err := DB.Save(want).Error; err != nil {
1559                 t.Error(err)
1560         }
1561
1562         got := new(Level1)
1563         err := DB.Preload("Level2.Level3s.Level4").Last(&got).Error
1564         if err != nil {
1565                 t.Error(err)
1566         }
1567
1568         if !reflect.DeepEqual(got, want) {
1569                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
1570         }
1571 }
1572
1573 func TestPrefixedPreloadDuplication(t *testing.T) {
1574         type (
1575                 Level4 struct {
1576                         ID       uint
1577                         Name     string
1578                         Level3ID uint
1579                 }
1580                 Level3 struct {
1581                         ID      uint
1582                         Name    string
1583                         Level4s []*Level4
1584                 }
1585                 Level2 struct {
1586                         ID       uint
1587                         Name     string
1588                         Level3ID sql.NullInt64 `sql:"index"`
1589                         Level3   *Level3
1590                 }
1591                 Level1 struct {
1592                         ID       uint
1593                         Name     string
1594                         Level2ID sql.NullInt64 `sql:"index"`
1595                         Level2   *Level2
1596                 }
1597         )
1598
1599         DB.DropTableIfExists(new(Level3))
1600         DB.DropTableIfExists(new(Level4))
1601         DB.DropTableIfExists(new(Level2))
1602         DB.DropTableIfExists(new(Level1))
1603
1604         if err := DB.AutoMigrate(new(Level3), new(Level4), new(Level2), new(Level1)).Error; err != nil {
1605                 t.Error(err)
1606         }
1607
1608         lvl := &Level3{}
1609         if err := DB.Save(lvl).Error; err != nil {
1610                 t.Error(err)
1611         }
1612
1613         sublvl1 := &Level4{Level3ID: lvl.ID}
1614         if err := DB.Save(sublvl1).Error; err != nil {
1615                 t.Error(err)
1616         }
1617         sublvl2 := &Level4{Level3ID: lvl.ID}
1618         if err := DB.Save(sublvl2).Error; err != nil {
1619                 t.Error(err)
1620         }
1621
1622         lvl.Level4s = []*Level4{sublvl1, sublvl2}
1623
1624         want1 := Level1{
1625                 Level2: &Level2{
1626                         Level3: lvl,
1627                 },
1628         }
1629         if err := DB.Save(&want1).Error; err != nil {
1630                 t.Error(err)
1631         }
1632
1633         want2 := Level1{
1634                 Level2: &Level2{
1635                         Level3: lvl,
1636                 },
1637         }
1638         if err := DB.Save(&want2).Error; err != nil {
1639                 t.Error(err)
1640         }
1641
1642         want := []Level1{want1, want2}
1643
1644         var got []Level1
1645         err := DB.Preload("Level2.Level3.Level4s").Find(&got).Error
1646         if err != nil {
1647                 t.Error(err)
1648         }
1649
1650         if !reflect.DeepEqual(got, want) {
1651                 t.Errorf("got %s; want %s", toJSONString(got), toJSONString(want))
1652         }
1653 }
1654
1655 func TestPreloadManyToManyCallbacks(t *testing.T) {
1656         type (
1657                 Level2 struct {
1658                         ID   uint
1659                         Name string
1660                 }
1661                 Level1 struct {
1662                         ID      uint
1663                         Name    string
1664                         Level2s []Level2 `gorm:"many2many:level1_level2s;AssociationForeignKey:ID;ForeignKey:ID"`
1665                 }
1666         )
1667
1668         DB.DropTableIfExists("level1_level2s")
1669         DB.DropTableIfExists(new(Level1))
1670         DB.DropTableIfExists(new(Level2))
1671
1672         if err := DB.AutoMigrate(new(Level1), new(Level2)).Error; err != nil {
1673                 t.Error(err)
1674         }
1675
1676         lvl := Level1{
1677                 Name: "l1",
1678                 Level2s: []Level2{
1679                         Level2{Name: "l2-1"}, Level2{Name: "l2-2"},
1680                 },
1681         }
1682         DB.Save(&lvl)
1683
1684         called := 0
1685
1686         DB.Callback().Query().After("gorm:query").Register("TestPreloadManyToManyCallbacks", func(scope *gorm.Scope) {
1687                 called = called + 1
1688         })
1689
1690         DB.Preload("Level2s").First(&Level1{}, "id = ?", lvl.ID)
1691
1692         if called != 3 {
1693                 t.Errorf("Wanted callback to be called 3 times but got %d", called)
1694         }
1695 }
1696
1697 func toJSONString(v interface{}) []byte {
1698         r, _ := json.MarshalIndent(v, "", "  ")
1699         return r
1700 }