Reintroduce conditional null-branch pruning and add direct-to-HRI option
[dbsrgits/DBIx-Class.git] / t / prefetch / manual.t
CommitLineData
69ab63d4 1use strict;
2use warnings;
3
4use Test::More;
5use Test::Exception;
6use lib qw(t/lib);
7use DBICTest;
8
908aa1bb 9my $schema = DBICTest->init_schema(no_populate => 1);
10
742280c7 11$schema->resultset('Artist')->create({ name => 'JMJ', cds => [{
12 title => 'Magnetic Fields',
13 year => 1981,
14 genre => { name => 'electro' },
15 tracks => [
16 { title => 'm1' },
17 { title => 'm2' },
18 { title => 'm3' },
19 { title => 'm4' },
20 ],
21} ] });
22
908aa1bb 23$schema->resultset('CD')->create({
24 title => 'Equinoxe',
25 year => 1978,
26 artist => { name => 'JMJ' },
27 genre => { name => 'electro' },
28 tracks => [
29 { title => 'e1' },
30 { title => 'e2' },
31 { title => 'e3' },
32 ],
33 single_track => {
34 title => 'o1',
35 cd => {
36 title => 'Oxygene',
37 year => 1976,
742280c7 38 artist => { name => 'JMJ' },
908aa1bb 39 tracks => [
40 { title => 'o2', position => 2}, # the position should not be here, bug in MC
41 ],
42 },
43 },
44});
69ab63d4 45
46my $rs = $schema->resultset ('CD')->search ({}, {
47 join => [ 'tracks', { single_track => { cd => { artist => { cds => 'tracks' } } } } ],
48 collapse => 1,
49 columns => [
50 { 'year' => 'me.year' }, # non-unique
51 { 'genreid' => 'me.genreid' }, # nullable
52 { 'tracks.title' => 'tracks.title' }, # non-unique (no me.id)
53 { 'single_track.cd.artist.cds.cdid' => 'cds.cdid' }, # to give uniquiness to ...tracks.title below
3904d3c3 54 { 'single_track.cd.artist.artistid' => 'artist.artistid' }, # uniqufies entire parental chain
69ab63d4 55 { 'single_track.cd.artist.cds.year' => 'cds.year' }, # non-unique
56 { 'single_track.cd.artist.cds.genreid' => 'cds.genreid' }, # nullable
57 { 'single_track.cd.artist.cds.tracks.title' => 'tracks_2.title' }, # unique when combined with ...cds.cdid above
908aa1bb 58 { 'latest_cd' => \ "(SELECT MAX(year) FROM cd)" }, # random function
3904d3c3 59 { 'title' => 'me.title' }, # uniquiness for me
60 { 'artist' => 'me.artist' }, # uniquiness for me
69ab63d4 61 ],
908aa1bb 62 order_by => [{ -desc => 'cds.year' }, { -desc => 'me.title'} ],
69ab63d4 63});
64
908aa1bb 65my $hri_rs = $rs->search({}, { result_class => 'DBIx::Class::ResultClass::HashRefInflator' });
66
67is_deeply (
68 [$hri_rs->all],
69 [
70 {
71 artist => 1,
72 genreid => 1,
73 latest_cd => 1981,
74 single_track => {
75 cd => {
76 artist => {
77 artistid => 1,
78 cds => [
79 {
80 cdid => 1,
81 genreid => 1,
82 tracks => [
83 {
84 title => "m1"
85 },
86 {
87 title => "m2"
88 },
89 {
90 title => "m3"
91 },
92 {
93 title => "m4"
94 }
95 ],
96 year => 1981
97 },
98 {
99 cdid => 3,
100 genreid => 1,
101 tracks => [
102 {
103 title => "e1"
104 },
105 {
106 title => "e2"
107 },
108 {
109 title => "e3"
110 }
111 ],
112 year => 1978
113 },
114 {
115 cdid => 2,
116 genreid => undef,
117 tracks => [
118 {
119 title => "o1"
120 },
121 {
122 title => "o2"
123 }
124 ],
125 year => 1976
126 }
127 ]
128 }
129 }
130 },
131 title => "Equinoxe",
132 tracks => [
133 {
134 title => "e1"
135 },
136 {
137 title => "e2"
138 },
139 {
140 title => "e3"
141 }
142 ],
143 year => 1978
144 },
145 {
146 artist => 1,
147 genreid => undef,
148 latest_cd => 1981,
149 single_track => undef,
150 title => "Oxygene",
151 tracks => [
152 {
153 title => "o1"
154 },
155 {
156 title => "o2"
157 }
158 ],
159 year => 1976
160 },
161 {
162 artist => 1,
163 genreid => 1,
164 latest_cd => 1981,
165 single_track => undef,
166 title => "Magnetic Fields",
167 tracks => [
168 {
169 title => "m1"
170 },
171 {
172 title => "m2"
173 },
174 {
175 title => "m3"
176 },
177 {
178 title => "m4"
179 }
180 ],
181 year => 1981
182 },
183 ],
184 'W00T, manual prefetch with collapse works'
185);
186
908aa1bb 187TODO: {
fcf32d04 188 my $row = $rs->next;
908aa1bb 189 local $TODO = 'Something is wrong with filter type rels, they throw on incomplete objects >.<';
190
191 lives_ok {
192 is_deeply (
193 { $row->single_track->get_columns },
194 {},
195 'empty intermediate object ok',
196 )
197 } 'no exception';
198}
69ab63d4 199
908aa1bb 200is ($rs->cursor->next, undef, 'cursor exhausted');
69ab63d4 201
fcf32d04 202
4e9fc3f3 203TODO: {
204local $TODO = 'this does not work at all, need to promote rsattrs to an object on its own';
205# make sure has_many column redirection does not do weird stuff when collapse is requested
206for my $pref_args (
207 { prefetch => 'cds'},
208 { collapse => 1 }
209) {
210 for my $col_and_join_args (
211 { '+columns' => { 'cd_title' => 'cds_2.title' }, join => [ 'cds', 'cds' ] },
212 { '+columns' => { 'cd_title' => 'cds.title' }, join => 'cds', }
213 ) {
214
215 my $weird_rs = $schema->resultset('Artist')->search({}, {
216 %$col_and_join_args, %$pref_args,
217 });
218
219 for (qw/next all first/) {
220 throws_ok { $weird_rs->$_ } qr/not yet determined exception text/;
221 }
222 }
223}
224}
225
fcf32d04 226# multi-has_many with underdefined root, with rather random order
227$rs = $schema->resultset ('CD')->search ({}, {
228 join => [ 'tracks', { single_track => { cd => { artist => { cds => 'tracks' } } } } ],
229 collapse => 1,
230 columns => [
231 { 'single_track.trackid' => 'single_track.trackid' }, # definitive link to root from 1:1:1:1:M:M chain
232 { 'year' => 'me.year' }, # non-unique
233 { 'tracks.cd' => 'tracks.cd' }, # \ together both uniqueness for second multirel
234 { 'tracks.title' => 'tracks.title' }, # / and definitive link back to root
235 { 'single_track.cd.artist.cds.cdid' => 'cds.cdid' }, # to give uniquiness to ...tracks.title below
236 { 'single_track.cd.artist.cds.year' => 'cds.year' }, # non-unique
237 { 'single_track.cd.artist.artistid' => 'artist.artistid' }, # uniqufies entire parental chain
238 { 'single_track.cd.artist.cds.genreid' => 'cds.genreid' }, # nullable
239 { 'single_track.cd.artist.cds.tracks.title' => 'tracks_2.title' }, # unique when combined with ...cds.cdid above
240 ],
241});
242
243for (1..3) {
244 $rs->create({ artist => 1, year => 1977, title => "fuzzy_$_" });
245}
246
247my $rs_random = $rs->search({}, { order_by => \ 'RANDOM()' });
248is ($rs_random->count, 6, 'row count matches');
249
250if ($ENV{TEST_VERBOSE}) {
251 my @lines = (
252 [ "What are we actually trying to collapse (Select/As, tests below will see a *DIFFERENT* random order):" ],
253 [ map { my $s = $_; $s =~ s/single_track\./sngl_tr./; $s } @{$rs_random->{_attrs}{select} } ],
254 $rs_random->{_attrs}{as},
255 [ "-" x 159 ],
256 $rs_random->cursor->all,
257 );
258
259 diag join ' # ', map { sprintf '% 15s', (defined $_ ? $_ : 'NULL') } @$_
260 for @lines;
261}
262
263my $queries = 0;
264$schema->storage->debugcb(sub { $queries++ });
265my $orig_debug = $schema->storage->debug;
266$schema->storage->debug (1);
267
268for my $use_next (0, 1) {
269 my @random_cds;
270 if ($use_next) {
271 while (my $o = $rs_random->next) {
272 push @random_cds, $o;
273 }
274 }
275 else {
276 @random_cds = $rs_random->all;
277 }
278
279 is (@random_cds, 6, 'object count matches');
280
281 for my $cd (@random_cds) {
282 if ($cd->year == 1977) {
283 is( scalar $cd->tracks, 0, 'no tracks on 1977 cd' );
284 is( $cd->single_track, undef, 'no single_track on 1977 cd' );
285 }
286 elsif ($cd->year == 1976) {
287 is( scalar $cd->tracks, 2, 'Two tracks on 1976 cd' );
288 like( $_->title, qr/^o\d/, "correct title" )
289 for $cd->tracks;
290 is( $cd->single_track, undef, 'no single_track on 1976 cd' );
291 }
292 elsif ($cd->year == 1981) {
293 is( scalar $cd->tracks, 4, 'Four tracks on 1981 cd' );
294 like( $_->title, qr/^m\d/, "correct title" )
295 for $cd->tracks;
296 is( $cd->single_track, undef, 'no single_track on 1981 cd' );
297 }
298 elsif ($cd->year == 1978) {
299 is( scalar $cd->tracks, 3, 'Three tracks on 1978 cd' );
300 like( $_->title, qr/^e\d/, "correct title" )
301 for $cd->tracks;
302 ok( defined $cd->single_track, 'single track prefetched on 1987 cd' );
ce556881 303 is( $cd->single_track->cd->artist->id, 1, 'Single_track->cd->artist prefetched on 1978 cd' );
304 is( scalar $cd->single_track->cd->artist->cds, 6, '6 cds prefetched on artist' );
fcf32d04 305 }
306 }
307}
308
309$schema->storage->debugcb(undef);
310$schema->storage->debug($orig_debug);
311is ($queries, 2, "Only two queries for rwo prefetch calls total");
312
313# can't is_deeply a random set - need *some* order
314my @hris = sort { $a->{year} cmp $b->{year} } @{$rs->search({}, {
315 order_by => [ 'tracks_2.title', 'tracks.title', 'cds.cdid', \ 'RANDOM()' ],
316})->all_hri};
317is (@hris, 6, 'hri count matches' );
318
319is_deeply (\@hris, [
320 {
321 single_track => undef,
322 tracks => [
323 {
324 cd => 2,
325 title => "o1"
326 },
327 {
328 cd => 2,
329 title => "o2"
330 }
331 ],
332 year => 1976
333 },
334 {
335 single_track => undef,
336 tracks => [],
337 year => 1977
338 },
339 {
340 single_track => undef,
341 tracks => [],
342 year => 1977
343 },
344 {
345 single_track => undef,
346 tracks => [],
347 year => 1977
348 },
349 {
350 single_track => {
351 cd => {
352 artist => {
353 artistid => 1,
354 cds => [
355 {
356 cdid => 4,
357 genreid => undef,
358 tracks => [],
359 year => 1977
360 },
361 {
362 cdid => 5,
363 genreid => undef,
364 tracks => [],
365 year => 1977
366 },
367 {
368 cdid => 6,
369 genreid => undef,
370 tracks => [],
371 year => 1977
372 },
373 {
374 cdid => 3,
375 genreid => 1,
376 tracks => [
377 {
378 title => "e1"
379 },
380 {
381 title => "e2"
382 },
383 {
384 title => "e3"
385 }
386 ],
387 year => 1978
388 },
389 {
390 cdid => 1,
391 genreid => 1,
392 tracks => [
393 {
394 title => "m1"
395 },
396 {
397 title => "m2"
398 },
399 {
400 title => "m3"
401 },
402 {
403 title => "m4"
404 }
405 ],
406 year => 1981
407 },
408 {
409 cdid => 2,
410 genreid => undef,
411 tracks => [
412 {
413 title => "o1"
414 },
415 {
416 title => "o2"
417 }
418 ],
419 year => 1976
420 }
421 ]
422 }
423 },
424 trackid => 6
425 },
426 tracks => [
427 {
428 cd => 3,
429 title => "e1"
430 },
431 {
432 cd => 3,
433 title => "e2"
434 },
435 {
436 cd => 3,
437 title => "e3"
438 },
439 ],
440 year => 1978
441 },
442 {
443 single_track => undef,
444 tracks => [
445 {
446 cd => 1,
447 title => "m1"
448 },
449 {
450 cd => 1,
451 title => "m2"
452 },
453 {
454 cd => 1,
455 title => "m3"
456 },
457 {
458 cd => 1,
459 title => "m4"
460 },
461 ],
462 year => 1981
463 },
464], 'W00T, multi-has_many manual underdefined root prefetch with collapse works');
465
908aa1bb 466done_testing;