Some cosmetic fixes in ANFANG
[dbsrgits/DBIx-Class.git] / t / resultset / inflate_result_api.t
1 BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
2
3 use strict;
4 use warnings;
5 no warnings 'exiting';
6
7 use Test::More;
8 use Test::Deep;
9 use Test::Exception;
10
11 use DBICTest;
12
13 my $schema = DBICTest->init_schema(no_populate => 1);
14
15 $schema->resultset('Artist')->create({ name => 'JMJ', cds => [{
16   title => 'Magnetic Fields',
17   year => 1981,
18   genre => { name => 'electro' },
19   tracks => [
20     { title => 'm1' },
21     { title => 'm2' },
22     { title => 'm3' },
23     { title => 'm4' },
24   ],
25 } ] });
26
27 $schema->resultset('CD')->create({
28   title => 'Equinoxe',
29   year => 1978,
30   artist => { name => 'JMJ' },
31   genre => { name => 'electro' },
32   tracks => [
33     { title => 'e1' },
34     { title => 'e2' },
35     { title => 'e3' },
36   ],
37   single_track => {
38     title => 'o1',
39     cd => {
40       title => 'Oxygene',
41       year => 1976,
42       artist => { name => 'JMJ' },
43       artwork => {},
44       tracks => [
45         { title => 'o2', position => 2},  # the position should not be needed here, bug in MC
46       ],
47     },
48   },
49 });
50
51 $schema->resultset('CD')->create({ artist => 1, year => 1977, title => "fuzzy_1" });
52
53 $schema->resultset('Artist')->create({ name => "${_}_cdless" })
54   for (qw( Z A ));
55
56 # subs at the end of the test refer to this
57 my $native_inflator;
58
59 ### TESTS START
60 # run entire test twice - with and without "native inflator"
61 INFTYPE: for ('', '(native inflator)') {
62
63   $native_inflator = $_;
64
65   cmp_structures(
66     rs_contents( $schema->resultset ('CD')->search_rs ({}, {
67       prefetch => { single_track => { cd => 'artist' } },
68       order_by => 'me.cdid',
69     }) ),
70     [
71       [
72         { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" },
73         { single_track => code(sub { null_branch ( \@_, [
74           { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
75           {  cd => code(sub { null_branch ( \@_, [
76             { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
77             {
78               artist => code(sub { null_branch ( \@_, [
79                 { artistid => undef, name => undef, charfield => undef, rank => undef }
80               ] ) } )
81             }
82           ] ) } ) }
83         ] ) } ) }
84       ],
85       [
86         { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" },
87         { single_track => code(sub { null_branch ( \@_, [
88           { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
89           {  cd => code(sub { null_branch ( \@_, [
90             { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
91             {
92               artist => code(sub { null_branch ( \@_, [
93                 { artistid => undef, name => undef, charfield => undef, rank => undef }
94               ] ) } )
95             }
96           ] ) } ) }
97         ] ) } ) }
98       ],
99       [
100         { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" },
101         { single_track => [
102           { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef },
103           {  cd => [
104             { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" },
105             {
106               artist => [
107                 { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }
108               ]
109             }
110           ] }
111         ] }
112       ],
113       [
114         { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" },
115         { single_track => code(sub { null_branch ( \@_, [
116           { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
117           {  cd => code(sub { null_branch ( \@_, [
118             { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
119             {
120               artist => code(sub { null_branch ( \@_, [
121                 { artistid => undef, name => undef, charfield => undef, rank => undef }
122               ] ) } )
123             }
124           ] ) } ) }
125         ] ) } ) }
126       ],
127     ],
128     "Simple 1:1 descend with classic prefetch $native_inflator"
129   );
130
131   cmp_structures(
132     rs_contents( $schema->resultset ('CD')->search_rs ({}, {
133       join => { single_track => { cd => 'artist' } },
134       columns => [
135         { 'year'                                    => 'me.year' },
136         { 'genreid'                                 => 'me.genreid' },
137         { 'single_track.cd.artist.artistid'         => 'artist.artistid' },
138         { 'title'                                   => 'me.title' },
139         { 'artist'                                  => 'me.artist' },
140       ],
141       order_by => 'me.cdid',
142     }) ),
143     [
144       [
145         { artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" },
146         { single_track => code(sub { null_branch ( \@_, [
147           undef,
148           {  cd => [
149             undef,
150             {
151               artist => [
152                 { artistid => undef }
153               ]
154             }
155           ] }
156         ] ) } ) }
157       ],
158       [
159         { artist => 1, genreid => undef, year => 1976, title => "Oxygene" },
160         { single_track => code(sub { null_branch ( \@_, [
161           undef,
162           {  cd => [
163             undef,
164             {
165               artist => [
166                 { artistid => undef }
167               ]
168             }
169           ] }
170         ] ) } ) }
171       ],
172       [
173         { artist => 1, genreid => 1, year => 1978, title => "Equinoxe" },
174         { single_track => [
175           undef,
176           {  cd => [
177             undef,
178             {
179               artist => [
180                 { artistid => 1 }
181               ]
182             }
183           ] }
184         ] }
185       ],
186       [
187         { artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" },
188         { single_track => code(sub { null_branch ( \@_, [
189           undef,
190           {  cd => [
191             undef,
192             {
193               artist => [
194                 { artistid => undef }
195               ]
196             }
197           ] }
198         ] ) } ) }
199       ],
200     ],
201     "Simple 1:1 descend with missing selectors $native_inflator",
202   );
203
204   cmp_structures(
205     rs_contents( $schema->resultset ('CD')->search_rs ({}, {
206       prefetch => [ { single_track => { cd => { artist => { cds => 'tracks' } } } } ],
207       order_by => [qw/me.cdid tracks.trackid/],
208     }) ),
209     [
210       [
211         { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" },
212         { single_track => code(sub { null_collapsed_branch ( \@_, [
213           { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
214           {  cd => [
215             { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
216             {
217               artist => [
218                 { artistid => undef, name => undef, charfield => undef, rank => undef },
219                 { cds => code(sub { null_collapsed_branch ( \@_, [ [
220                   { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
221                   { tracks => code(sub { null_collapsed_branch ( \@_, [ [
222                     { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
223                   ] ] ) } ) },
224                 ] ] ) } ) },
225               ],
226             },
227           ] },
228         ] ) } ) },
229       ],
230       [
231         { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" },
232         { single_track => code(sub { null_collapsed_branch ( \@_, [
233           { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
234           {  cd => [
235             { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
236             {
237               artist => [
238                 { artistid => undef, name => undef, charfield => undef, rank => undef },
239                 { cds => code(sub { null_collapsed_branch ( \@_, [ [
240                   { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
241                   { tracks => code(sub { null_collapsed_branch ( \@_, [ [
242                     { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
243                   ] ] ) } ) },
244                 ] ] ) } ) },
245               ],
246             },
247           ] },
248         ] ) } ) },
249       ],
250       [
251         { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" },
252         { single_track => [
253           { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef },
254           {  cd => [
255             { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" },
256             {
257               artist => [
258                 { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
259                 { cds => [
260                   [
261                     { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" },
262                     { tracks => code(sub { null_collapsed_branch ( \@_, [
263                       [ { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef } ],
264                     ] ) } ) },
265                   ],
266                   [
267                     { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" },
268                     { tracks => [
269                       [ { trackid => 1, title => 'm1', position => 1, cd => 1, last_updated_at => undef, last_updated_on => undef } ],
270                       [ { trackid => 2, title => 'm2', position => 2, cd => 1, last_updated_at => undef, last_updated_on => undef } ],
271                       [ { trackid => 3, title => 'm3', position => 3, cd => 1, last_updated_at => undef, last_updated_on => undef } ],
272                       [ { trackid => 4, title => 'm4', position => 4, cd => 1, last_updated_at => undef, last_updated_on => undef } ],
273                     ]},
274                   ],
275                   [
276                     { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" },
277                     { tracks => [
278                       [ { trackid => 5, title => 'o2', position => 2, cd => 2, last_updated_at => undef, last_updated_on => undef } ],
279                       [ { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef } ],
280                     ]},
281                   ],
282                   [
283                     { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" },
284                     { tracks => [
285                       [ { trackid => 7, title => 'e1', position => 1, cd => 3, last_updated_at => undef, last_updated_on => undef } ],
286                       [ { trackid => 8, title => 'e2', position => 2, cd => 3, last_updated_at => undef, last_updated_on => undef } ],
287                       [ { trackid => 9, title => 'e3', position => 3, cd => 3, last_updated_at => undef, last_updated_on => undef } ],
288                     ]},
289                   ],
290                 ]},
291               ]
292             }
293           ] }
294         ] }
295       ],
296       [
297         { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" },
298         { single_track => code(sub { null_collapsed_branch ( \@_, [
299           { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
300           {  cd => [
301             { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
302             {
303               artist => [
304                 { artistid => undef, name => undef, charfield => undef, rank => undef },
305                 { cds => code(sub { null_collapsed_branch ( \@_, [ [
306                   { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
307                   { tracks => code(sub { null_collapsed_branch ( \@_, [ [
308                     { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
309                   ] ] ) } ) },
310                 ] ] ) } ) },
311               ],
312             },
313           ] },
314         ] ) } ) },
315       ],
316     ],
317     "Collapsing 1:1 ending in chained has_many with classic prefetch $native_inflator",
318   );
319
320   cmp_structures (
321     rs_contents( $schema->resultset ('Artist')->search_rs ({}, {
322       join => { cds => 'tracks' },
323       '+columns' => [
324         (map { "cds.$_" } $schema->source('CD')->columns),
325         (map { +{ "cds.tracks.$_" => "tracks.$_" } } $schema->source('Track')->columns),
326       ],
327       order_by => [qw/cds.cdid tracks.trackid me.name/],
328     }) ),
329     [
330       [
331         { artistid => 3, name => 'A_cdless', charfield => undef, rank => 13 },
332         { cds => code(sub { null_branch ( \@_, [
333           { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
334           { tracks => code(sub { null_branch ( \@_, [
335             { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
336           ] ) } ) },
337         ] ) } ) },
338       ],
339       [
340         { artistid => 2, name => 'Z_cdless', charfield => undef, rank => 13 },
341         { cds => code(sub { null_branch ( \@_, [
342           { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef },
343           { tracks => code(sub { null_branch ( \@_, [
344             { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
345           ] ) } ) },
346         ] ) } ) },
347       ],
348       [
349         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
350         { cds => [
351           { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" },
352           { tracks => [
353             { trackid => 1, title => 'm1', position => 1, cd => 1, last_updated_at => undef, last_updated_on => undef },
354           ]},
355         ]},
356       ],
357       [
358         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
359         { cds => [
360           { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" },
361           { tracks => [
362             { trackid => 2, title => 'm2', position => 2, cd => 1, last_updated_at => undef, last_updated_on => undef },
363           ]},
364         ]},
365       ],
366       [
367         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
368         { cds => [
369           { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" },
370           { tracks => [
371             { trackid => 3, title => 'm3', position => 3, cd => 1, last_updated_at => undef, last_updated_on => undef },
372           ]},
373         ]},
374       ],
375       [
376         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
377         { cds => [
378           { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" },
379           { tracks => [
380             { trackid => 4, title => 'm4', position => 4, cd => 1, last_updated_at => undef, last_updated_on => undef },
381           ]},
382         ]},
383       ],
384       [
385         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
386         { cds => [
387           { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" },
388           { tracks => [
389             { trackid => 5, title => 'o2', position => 2, cd => 2, last_updated_at => undef, last_updated_on => undef },
390           ]},
391         ]},
392       ],
393       [
394         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
395         { cds => [
396           { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" },
397           { tracks => [
398             { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef },
399           ]},
400         ]},
401       ],
402       [
403         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
404         { cds => [
405           { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" },
406           { tracks => [
407             { trackid => 7, title => 'e1', position => 1, cd => 3, last_updated_at => undef, last_updated_on => undef },
408           ]},
409         ]},
410       ],
411       [
412         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
413         { cds => [
414           { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" },
415           { tracks => [
416             { trackid => 8, title => 'e2', position => 2, cd => 3, last_updated_at => undef, last_updated_on => undef },
417           ]},
418         ]},
419       ],
420       [
421         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
422         { cds => [
423           { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" },
424           { tracks => [
425             { trackid => 9, title => 'e3', position => 3, cd => 3, last_updated_at => undef, last_updated_on => undef },
426           ]},
427         ]},
428       ],
429       [
430         { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 },
431         { cds => [
432           { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" },
433           { tracks => code(sub { null_branch ( \@_, [
434             { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef },
435           ] ) } ) },
436         ]},
437       ],
438     ],
439     "Non-Collapsing chained has_many $native_inflator",
440   );
441
442   cmp_structures (
443     rs_contents( $schema->resultset ('Artist')->search_rs ({}, {
444       collapse => 1,
445       join => 'cds',
446       columns => [qw( cds.title cds.artist )],
447       order_by => [qw( me.name cds.title )],
448     }) ),
449     [
450       [
451         undef,
452         { cds => code(sub { null_collapsed_branch ( \@_, [
453           [ { artist => undef, title => undef } ]
454         ] ) } ) },
455       ],
456       [
457         undef,
458         { cds => [
459           [ { artist => 1, title => "Equinoxe" } ],
460           [ { artist => 1, title => "Magnetic Fields" } ],
461           [ { artist => 1, title => "Oxygene" } ],
462           [ { artist => 1, title => "fuzzy_1" } ],
463         ] }
464       ],
465       [
466         undef,
467         { cds => code(sub { null_collapsed_branch ( \@_, [
468           [ { artist => undef, title => undef } ]
469         ] ) } ) },
470       ],
471     ],
472     "Expected output of collapsing 1:M with empty root selection $native_inflator",
473   );
474
475   cmp_structures (
476     rs_contents( $schema->resultset ('CD')->search_rs (
477       {
478         'tracks.title' => 'e2',
479         'cds.title' => 'Oxygene',
480       },
481       {
482         collapse => 1,
483         join => [
484           'tracks',
485           { single_track => { cd => 'mandatory_artwork' } },
486           { artist => { cds => 'mandatory_artwork'} },
487         ],
488         columns => {
489           cdid                                      => 'cdid',
490           'single_track.cd.mandatory_artwork.cd_id' => 'mandatory_artwork.cd_id',
491           'artist.cds.mandatory_artwork.cd_id'      => 'mandatory_artwork_2.cd_id',
492         },
493       },
494     )),
495     [[
496       { cdid => 3 },
497       {
498         single_track => [
499           undef,
500           { cd => [
501             undef,
502             { mandatory_artwork => [ { cd_id => 2 } ] }
503           ] }
504         ],
505         artist => [
506           undef,
507           { cds => [
508             [
509               undef,
510               { mandatory_artwork => [ { cd_id => 2 } ] }
511             ]
512           ] },
513         ],
514       }
515     ]],
516   );
517 }
518
519 sub null_branch {
520   cmp_deeply(
521     $_[0][0],
522     $native_inflator ? undef : bless( $_[1], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ),
523   );
524 }
525 sub null_collapsed_branch {
526   cmp_deeply(
527     $_[0][0],
528     $native_inflator ? [] : bless( $_[1], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ),
529   );
530 }
531
532 {
533   package DBICTest::_IRCapture;
534   sub inflate_result { [@_[2,3]] };
535 }
536
537 sub rs_contents {
538   my $rs = shift;
539   $rs->result_class('DBICTest::_IRCapture');
540   die 'eeeeek - preprocessed $rs' if defined $rs->{_result_inflator}{is_core_row};
541   $rs->{_result_inflator}{is_core_row} = 1 if $native_inflator;
542   [$rs->all],
543 }
544
545 sub cmp_structures {
546   my ($left, $right, $msg) = @_;
547
548   local $Test::Builder::Level = $Test::Builder::Level + 1;
549   cmp_deeply($left, $right, $msg||()) or next INFTYPE;
550 }
551
552
553 {
554   package DBICTest::_DoubleResult;
555
556   sub inflate_result {
557     my $class = shift;
558     return map { DBIx::Class::ResultClass::HashRefInflator->inflate_result(@_) } (1,2);
559   }
560 }
561
562 my $oxygene_rs = $schema->resultset('CD')->search({ 'me.title' => 'Oxygene' });
563
564 is_deeply(
565   [ $oxygene_rs->search({}, { result_class => 'DBICTest::_DoubleResult' })->all ],
566   [ ({ $oxygene_rs->single->get_columns }) x 2 ],
567 );
568
569 is_deeply(
570   [ $oxygene_rs->search({}, {
571     result_class => 'DBICTest::_DoubleResult', prefetch => [qw(artist tracks)],
572     order_by => [qw(me.cdid tracks.title)],
573   })->all ],
574   [ (@{$oxygene_rs->search({}, {
575     prefetch=> [qw(artist tracks)],
576     order_by => [qw(me.cdid tracks.title)],
577   })->all_hri}) x 2 ],
578 );
579
580
581 {
582   package DBICTest::_DieTrying;
583
584   sub inflate_result {
585     die "nyah nyah nyah";
586   }
587 }
588
589 throws_ok {
590   $schema->resultset('CD')->search({}, { result_class => 'DBICTest::_DieTrying' })->all
591 } qr/nyah nyah nyah/, 'Exception in custom inflate_result propagated correctly';
592
593
594 done_testing;