Switch the main dev branch back to 'master'
[dbsrgits/DBIx-Class.git] / t / prefetch / multiple_hasmany_torture.t
1 use strict;
2 use warnings;
3
4 use Test::More;
5 use Test::Deep;
6 use Test::Exception;
7 use lib qw(t/lib);
8 use DBICTest;
9 use DBIx::Class::_Util 'sigwarn_silencer';
10
11 my $schema = DBICTest->init_schema();
12
13 $schema->resultset('Artist')->create(
14   {
15     name => 'mo',
16     rank => '1337',
17     cds  => [
18       {
19         title  => 'Song of a Foo',
20         year   => '1999',
21         tracks => [
22           { title  => 'Foo Me Baby One More Time' },
23           { title  => 'Foo Me Baby One More Time II' },
24           { title  => 'Foo Me Baby One More Time III' },
25           { title  => 'Foo Me Baby One More Time IV', cd_single => {
26             artist => 1, title => 'MO! Single', year => 2021, tracks => [
27               { title => 'singled out' },
28               { title => 'still alone' },
29             ]
30           } }
31         ],
32         cd_to_producer => [
33           { producer => { name => 'riba' } },
34           { producer => { name => 'sushi' } },
35         ]
36       },
37       {
38         title  => 'Song of a Foo II',
39         year   => '2002',
40         tracks => [
41           { title  => 'Quit Playing Games With My Heart' },
42           { title  => 'Bar Foo' },
43           { title  => 'Foo Bar', cd_single => {
44             artist => 2, title => 'MO! Single', year => 2020, tracks => [
45               { title => 'singled out' },
46               { title => 'still alone' },
47             ]
48           } }
49         ],
50         cd_to_producer => [
51           { producer => { name => 'riba' } },
52           { producer => { name => 'sushi' } },
53         ],
54       }
55     ],
56     artwork_to_artist => [
57       { artwork => { cd_id => 1 } },
58       { artwork => { cd_id => 2 } }
59     ]
60   }
61 );
62
63 my $artist_with_extras = {
64   artistid => 4, charfield => undef, name => 'mo', rank => 1337,
65   artwork_to_artist => [
66     { artist_id => 4, artwork_cd_id => 1, artwork => { cd_id => 1 } },
67     { artist_id => 4, artwork_cd_id => 2, artwork => { cd_id => 2 } },
68   ],
69   cds => [
70     {
71       artist => 4, cdid => 6, title => 'Song of a Foo', genreid => undef, year => 1999, single_track => undef,
72       cd_to_producer => [
73         { attribute => undef, cd => 6, producer => { name => 'riba', producerid => 4 } },
74         { attribute => undef, cd => 6, producer => { name => 'sushi', producerid => 5 } },
75       ],
76       tracks => [
77         { cd => 6, position => 1, trackid => 19, title => 'Foo Me Baby One More Time', last_updated_on => undef, last_updated_at => undef, cd_single => undef },
78         { cd => 6, position => 2, trackid => 20, title => 'Foo Me Baby One More Time II', last_updated_on => undef, last_updated_at => undef, cd_single => undef },
79         { cd => 6, position => 3, trackid => 21, title => 'Foo Me Baby One More Time III', last_updated_on => undef, last_updated_at => undef, cd_single => undef },
80         { cd => 6, position => 4, trackid => 22, title => 'Foo Me Baby One More Time IV', last_updated_on => undef, last_updated_at => undef, cd_single => {
81           single_track => 22, artist => 1, cdid => 7, title => 'MO! Single', genreid => undef, year => 2021, tracks => [
82             { cd => 7, position => 1, title => 'singled out', trackid => '23', last_updated_at => undef, last_updated_on => undef },
83             { cd => 7, position => 2, title => 'still alone', trackid => '24', last_updated_at => undef, last_updated_on => undef },
84           ],
85         } }
86       ],
87     },
88     {
89       artist => 4, cdid => 8, title => 'Song of a Foo II', genreid => undef, year => 2002, single_track => undef,
90       cd_to_producer => [
91         { attribute => undef, cd => 8, producer => { name => 'riba', producerid => 4 } },
92         { attribute => undef, cd => 8, producer => { name => 'sushi', producerid => 5 } },
93       ],
94       tracks => [
95         { cd => 8, position => 1, trackid => 25, title => 'Quit Playing Games With My Heart', last_updated_on => undef, last_updated_at => undef, cd_single => undef },
96         { cd => 8, position => 2, trackid => 26, title => 'Bar Foo', last_updated_on => undef, last_updated_at => undef, cd_single => undef },
97         { cd => 8, position => 3, trackid => 27, title => 'Foo Bar', last_updated_on => undef, last_updated_at => undef, cd_single => {
98           single_track => 27, artist => 2, cdid => 9, title => 'MO! Single', genreid => undef, year => 2020, tracks => [
99             { cd => 9, position => 1, title => 'singled out', trackid => '28', last_updated_at => undef, last_updated_on => undef },
100             { cd => 9, position => 2, title => 'still alone', trackid => '29', last_updated_at => undef, last_updated_on => undef },
101           ],
102         } }
103       ],
104     }
105   ],
106 };
107
108 my $art_rs = $schema->resultset('Artist')->search({ 'me.artistid' => 4 });
109
110
111 my $art_rs_prefetch = $art_rs->search({}, {
112   order_by => [qw/tracks.position tracks.trackid producer.producerid tracks_2.trackid artwork.cd_id/],
113   result_class => 'DBIx::Class::ResultClass::HashRefInflator',
114   prefetch => [
115     {
116       cds => [
117         { tracks => { cd_single => 'tracks' } },
118         { cd_to_producer => 'producer' }
119       ]
120     },
121     { artwork_to_artist => 'artwork' }
122   ],
123 });
124
125 cmp_deeply( $art_rs_prefetch->next, $artist_with_extras );
126
127
128 for my $order (
129   [ [qw( cds.cdid tracks.position )] ],
130
131   [ [qw( artistid tracks.cd tracks.position )],
132     'we need to proxy the knowledge from the collapser that tracks.cd is a stable sorter for CDs' ],
133 ) {
134
135   my $cds_rs_prefetch = $art_rs->related_resultset('cds')->search({}, {
136     order_by => [ $order->[0], qw(producer.name tracks_2.position) ],
137     result_class => 'DBIx::Class::ResultClass::HashRefInflator',
138     prefetch => [
139       { tracks => { cd_single => 'tracks' } },
140       { cd_to_producer => 'producer' },
141     ],
142   });
143
144   local $SIG{__WARN__} = sigwarn_silencer(qr/Unable to properly collapse has_many results/) if $order->[1];
145
146   cmp_deeply( $cds_rs_prefetch->next, $artist_with_extras->{cds}[0], '1st cd structure matches' );
147   cmp_deeply( $cds_rs_prefetch->next, $artist_with_extras->{cds}[1], '2nd cd structure matches' );
148
149   # INTERNALS! (a.k.a boars, gore and whores) DO NOT CARGOCULT!!!
150   local $TODO = $order->[1] if $order->[1];
151   ok( $cds_rs_prefetch->_resolved_attrs->{_ordered_for_collapse}, 'ordered_for_collapse detected properly' );
152 }
153
154
155 done_testing;