@@ -6,6 +6,7 @@ defmodule Ecto.Integration.PreloadTest do
66
77 alias Ecto.Integration.Post
88 alias Ecto.Integration.Comment
9+ alias Ecto.Integration.CompositePk
910 alias Ecto.Integration.Item
1011 alias Ecto.Integration.Permalink
1112 alias Ecto.Integration.User
@@ -341,6 +342,25 @@ defmodule Ecto.Integration.PreloadTest do
341342 assert [ ] = pe3 . comments
342343 end
343344
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+
344364 test "preload many_to_many with function" do
345365 p1 = TestRepo . insert! ( % Post { title: "1" } )
346366 p2 = TestRepo . insert! ( % Post { title: "2" } )
@@ -389,6 +409,50 @@ defmodule Ecto.Integration.PreloadTest do
389409 assert p3 . users == [ % { id: uid1 } , % { id: uid4 } ]
390410 end
391411
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+
392456 test "preload with query" do
393457 p1 = TestRepo . insert! ( % Post { title: "1" } )
394458 p2 = TestRepo . insert! ( % Post { title: "2" } )
@@ -604,6 +668,18 @@ defmodule Ecto.Integration.PreloadTest do
604668 assert TestRepo . preload ( updated , [ :author ] , force: true ) . author == nil
605669 end
606670
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+
607683 test "preload skips already loaded for cardinality one" do
608684 % Post { id: pid } = TestRepo . insert! ( % Post { title: "1" } )
609685
0 commit comments