@@ -6,6 +6,7 @@ defmodule Ecto.Integration.PreloadTest do
6
6
7
7
alias Ecto.Integration.Post
8
8
alias Ecto.Integration.Comment
9
+ alias Ecto.Integration.CompositePk
9
10
alias Ecto.Integration.Item
10
11
alias Ecto.Integration.Permalink
11
12
alias Ecto.Integration.User
@@ -341,6 +342,25 @@ defmodule Ecto.Integration.PreloadTest do
341
342
assert [ ] = pe3 . comments
342
343
end
343
344
345
+ test "preload composite foreign key with function" do
346
+ c11 = TestRepo . insert! ( % CompositePk { a: 1 , b: 1 , name: "11" } )
347
+ c12 = TestRepo . insert! ( % CompositePk { a: 1 , b: 2 , name: "12" } )
348
+ c22 = TestRepo . insert! ( % CompositePk { a: 2 , b: 2 , name: "22" } )
349
+ c33 = TestRepo . insert! ( % CompositePk { a: 3 , b: 3 , name: "33" } )
350
+
351
+ TestRepo . insert! ( % Post { title: "1" , composite_a: 1 , composite_b: 1 } )
352
+ TestRepo . insert! ( % Post { title: "2" , composite_a: 1 , composite_b: 1 } )
353
+ TestRepo . insert! ( % Post { title: "3" , composite_a: 1 , composite_b: 2 } )
354
+ TestRepo . insert! ( % Post { title: "4" , composite_a: 2 , composite_b: 2 } )
355
+
356
+ assert [ ce12 , ce11 , ce33 , ce22 ] = TestRepo . preload ( [ c12 , c11 , c33 , c22 ] ,
357
+ posts: fn _ -> TestRepo . all ( Post ) end )
358
+ assert [ % Post { title: "1" } , % Post { title: "2" } ] = ce11 . posts
359
+ assert [ % Post { title: "3" } ] = ce12 . posts
360
+ assert [ % Post { title: "4" } ] = ce22 . posts
361
+ assert [ ] = ce33 . posts
362
+ end
363
+
344
364
test "preload many_to_many with function" do
345
365
p1 = TestRepo . insert! ( % Post { title: "1" } )
346
366
p2 = TestRepo . insert! ( % Post { title: "2" } )
@@ -389,6 +409,50 @@ defmodule Ecto.Integration.PreloadTest do
389
409
assert p3 . users == [ % { id: uid1 } , % { id: uid4 } ]
390
410
end
391
411
412
+ test "preload many_to_many on composite foreign keys with function" do
413
+ c11 = TestRepo . insert! ( % CompositePk { a: 1 , b: 1 , name: "11" } )
414
+ c12 = TestRepo . insert! ( % CompositePk { a: 1 , b: 2 , name: "12" } )
415
+ c22 = TestRepo . insert! ( % CompositePk { a: 2 , b: 2 , name: "22" } )
416
+
417
+ TestRepo . insert_all "composite_pk_composite_pk" , [ [ a_1: 1 , b_1: 1 , a_2: 1 , b_2: 2 ] ,
418
+ [ a_1: 1 , b_1: 1 , a_2: 2 , b_2: 2 ] ,
419
+ [ a_1: 1 , b_1: 2 , a_2: 1 , b_2: 1 ] ,
420
+ [ a_1: 2 , b_1: 2 , a_2: 2 , b_2: 2 ] ]
421
+
422
+ wrong_preloader = fn composite_ids ->
423
+ composite_ids_a = Enum . map ( composite_ids , & Enum . at ( & 1 , 0 ) )
424
+ composite_ids_b = Enum . map ( composite_ids , & Enum . at ( & 1 , 1 ) )
425
+ TestRepo . all (
426
+ from c in CompositePk ,
427
+ join: cc in "composite_pk_composite_pk" ,
428
+ where: cc . a_1 in ^ composite_ids_a and cc . b_1 in ^ composite_ids_b and cc . a_2 == c . a and cc . b_2 == c . b ,
429
+ order_by: [ c . a , c . b ] ,
430
+ select: map ( c , [ :name ] )
431
+ )
432
+ end
433
+
434
+ assert_raise RuntimeError , ~r/ invalid custom preload for `composites` on `Ecto.Integration.CompositePk`/ , fn ->
435
+ TestRepo . preload ( [ c11 , c12 , c22 ] , composites: wrong_preloader )
436
+ end
437
+
438
+ right_preloader = fn composite_ids ->
439
+ composite_ids_a = Enum . map ( composite_ids , & Enum . at ( & 1 , 0 ) )
440
+ composite_ids_b = Enum . map ( composite_ids , & Enum . at ( & 1 , 1 ) )
441
+ TestRepo . all (
442
+ from c in CompositePk ,
443
+ join: cc in "composite_pk_composite_pk" ,
444
+ where: cc . a_1 in ^ composite_ids_a and cc . b_1 in ^ composite_ids_b and cc . a_2 == c . a and cc . b_2 == c . b ,
445
+ order_by: [ c . a , c . b ] ,
446
+ select: { [ cc . a_1 , cc . b_1 ] , map ( c , [ :name ] ) }
447
+ )
448
+ end
449
+
450
+ [ c11 , c12 , c22 ] = TestRepo . preload ( [ c11 , c12 , c22 ] , composites: right_preloader )
451
+ assert c11 . composites == [ % { name: "12" } , % { name: "22" } ]
452
+ assert c12 . composites == [ % { name: "11" } ]
453
+ assert c22 . composites == [ % { name: "22" } ]
454
+ end
455
+
392
456
test "preload with query" do
393
457
p1 = TestRepo . insert! ( % Post { title: "1" } )
394
458
p2 = TestRepo . insert! ( % Post { title: "2" } )
@@ -604,6 +668,18 @@ defmodule Ecto.Integration.PreloadTest do
604
668
assert TestRepo . preload ( updated , [ :author ] , force: true ) . author == nil
605
669
end
606
670
671
+ test "preload raises with association over composite foreign key is set but without id" do
672
+ p1 = TestRepo . insert! ( % Post { title: "1" } )
673
+ c11 = TestRepo . insert! ( % CompositePk { a: 1 , b: 1 , name: "11" } )
674
+ updated = % { p1 | composite: c11 , composite_a: nil , composite_b: nil }
675
+
676
+ assert ExUnit.CaptureLog . capture_log ( fn ->
677
+ assert TestRepo . preload ( updated , [ :composite ] ) . composite == c11
678
+ end ) =~ ~r/ its association keys `\[ composite_a, composite_b\] ` are nil/
679
+
680
+ assert TestRepo . preload ( updated , [ :composite ] , force: true ) . composite == nil
681
+ end
682
+
607
683
test "preload skips already loaded for cardinality one" do
608
684
% Post { id: pid } = TestRepo . insert! ( % Post { title: "1" } )
609
685
0 commit comments