9 # globally set for the rest of test
10 # the rowparser maker does not order its hashes by default for the miniscule
11 # speed gain. But it does not disable sorting either - for this test
12 # everything will be ordered nicely, and the hash randomization of 5.18
13 # will not trip up anything
15 $Data::Dumper::Sortkeys = 1;
17 my $schema = DBICTest->init_schema(no_deploy => 1);
19 single_track.cd.artist.name
24 $schema->source ('CD')->_mk_row_parser({
25 inflate_map => $infmap,
29 { single_track => ( ! defined( $_->[0]) )
50 'Simple 1:1 descending non-collapsing parser',
54 single_track.cd.artist.cds.tracks.title
55 single_track.cd.artist.artistid
57 single_track.cd.artist.cds.cdid
63 $schema->source ('CD')->_mk_row_parser({
64 inflate_map => $infmap,
67 { artist => $_->[5], title => $_->[4], year => $_->[2] },
69 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
77 { artistid => $_->[1] },
79 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
83 tracks => ( ! defined $_->[0] )
84 ? bless ( [{ title => $_->[0] }], __NBC__ )
85 : [{ title => $_->[0] }]
91 tracks => ( ! defined $_->[0] )
92 ? bless ( [{ title => $_->[0] }], __NBC__ )
93 : [{ title => $_->[0] }]
109 { artistid => $_->[1] },
111 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
115 tracks => ( ! defined $_->[0] )
116 ? bless ( [{ title => $_->[0] }], __NBC__ )
117 : [{ title => $_->[0] }]
123 tracks => ( ! defined $_->[0] )
124 ? bless ( [{ title => $_->[0] }], __NBC__ )
125 : [{ title => $_->[0] }]
136 '1:1 descending non-collapsing parser terminating with chained 1:M:M',
140 $schema->source ('CD')->_mk_row_parser({
142 inflate_map => $infmap,
145 artist => $_->[5], title => $_->[4], year => $_->[2],
147 ( single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
154 ( cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
158 ( tracks => ( ! defined $_->[0] )
160 : { title => $_->[0] }
169 '1:1 descending non-collapsing HRI-direct parser terminating with chained 1:M:M',
175 ($schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} })),
177 -identifying_columns => [ 4, 5 ],
180 -identifying_columns => [ 1, 4, 5 ],
185 -identifying_columns => [ 1, 4, 5 ],
189 -identifying_columns => [ 1, 4, 5 ],
193 -identifying_columns => [ 1, 3, 4, 5 ],
197 -identifying_columns => [ 0, 1, 3, 4, 5 ],
205 'Correct collapse map for 1:1 descending chain terminating with chained 1:M:M'
209 $schema->source ('CD')->_mk_row_parser({
210 inflate_map => $infmap,
214 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
216 while ($cur_row_data = (
217 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
219 ( $_[1] and $rows_pos = -1 and $_[1]->() )
222 $cur_row_ids{0} = defined $cur_row_data->[0] ? $cur_row_data->[0] : "\0NULL\xFF$rows_pos\xFF0\0";
223 $cur_row_ids{1} = defined $cur_row_data->[1] ? $cur_row_data->[1] : "\0NULL\xFF$rows_pos\xFF1\0";
224 $cur_row_ids{3} = defined $cur_row_data->[3] ? $cur_row_data->[3] : "\0NULL\xFF$rows_pos\xFF3\0";
225 $cur_row_ids{4} = defined $cur_row_data->[4] ? $cur_row_data->[4] : "\0NULL\xFF$rows_pos\xFF4\0";
226 $cur_row_ids{5} = defined $cur_row_data->[5] ? $cur_row_data->[5] : "\0NULL\xFF$rows_pos\xFF5\0";
228 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
229 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} and (unshift @{$_[2]}, $cur_row_data) and last;
231 # the rowdata itself for root node
232 $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} ||= $_[0][$result_pos++] = [{ artist => $cur_row_data->[5], title => $cur_row_data->[4], year => $cur_row_data->[2] }];
234 # prefetch data of single_track (placed in root)
235 $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track} ||= $collapse_idx[1]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [];
236 defined($cur_row_data->[1]) or bless( $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track}, __NBC__ );
238 # prefetch data of cd (placed in single_track)
239 $collapse_idx[1]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [];
241 # prefetch data of artist ( placed in single_track->cd)
242 $collapse_idx[2]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ artistid => $cur_row_data->[1] }];
244 # prefetch data of cds (if available)
245 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
247 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}}, (
248 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ cdid => $cur_row_data->[3] }]
250 defined($cur_row_data->[3]) or bless( $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}, __NBC__ );
252 # prefetch data of tracks (if available)
253 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
255 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}}, (
256 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[0] }]
258 defined($cur_row_data->[0]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}, __NBC__ );
261 $#{$_[0]} = $result_pos - 1;
263 'Same 1:1 descending terminating with chained 1:M:M but with collapse',
267 $schema->source ('CD')->_mk_row_parser({
268 inflate_map => $infmap,
273 my ($result_pos, @collapse_idx, $cur_row_data);
275 while ($cur_row_data = (
276 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
278 ( $_[1] and $rows_pos = -1 and $_[1]->() )
281 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
282 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]} and (unshift @{$_[2]}, $cur_row_data) and last;
284 # the rowdata itself for root node
285 $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]} ||= $_[0][$result_pos++] = { artist => $cur_row_data->[5], title => $cur_row_data->[4], year => $cur_row_data->[2] };
287 # prefetch data of single_track (placed in root)
288 (! defined($cur_row_data->[1]) ) ? $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]}{single_track} = undef : do {
289 $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]}{single_track} ||= $collapse_idx[1]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]};
291 # prefetch data of cd (placed in single_track)
292 $collapse_idx[1]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cd} ||= $collapse_idx[2]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]};
294 # prefetch data of artist ( placed in single_track->cd)
295 $collapse_idx[2]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{artist} ||= $collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]} = { artistid => $cur_row_data->[1] };
297 # prefetch data of cds (if available)
298 (! defined $cur_row_data->[3] ) ? $collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cds} = [] : do {
300 (! $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} )
302 push @{$collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cds}}, (
303 $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} = { cdid => $cur_row_data->[3] }
306 # prefetch data of tracks (if available)
307 ( ! defined $cur_row_data->[0] ) ? $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]}{tracks} = [] : do {
309 (! $collapse_idx[5]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} )
311 push @{$collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]}{tracks}}, (
312 $collapse_idx[5]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} = { title => $cur_row_data->[0] }
318 $#{$_[0]} = $result_pos - 1;
320 'Same 1:1 descending terminating with chained 1:M:M but with collapse, HRI-direct',
324 tracks.lyrics.existing_lyric_versions.text
325 existing_single_track.cd.artist.artistid
326 existing_single_track.cd.artist.cds.year
330 existing_single_track.cd.artist.cds.cdid
332 existing_single_track.cd.artist.cds.tracks.title
333 existing_single_track.cd.artist.cds.genreid
334 tracks.lyrics.existing_lyric_versions.lyric_id
338 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
340 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
342 existing_single_track => {
343 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
347 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
351 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
355 -identifying_columns => [ 1, 6 ], # existing_single_track.cd.artist.cds.cdid
359 -identifying_columns => [ 1, 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title
367 -identifying_columns => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title
371 -identifying_columns => [ 1, 5, 10 ], # existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id
375 existing_lyric_versions => {
376 -identifying_columns => [ 0, 1, 5, 10 ], # tracks.lyrics.existing_lyric_versions.text, existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id
381 'Correct collapse map constructed',
385 $schema->source ('CD')->_mk_row_parser({
386 inflate_map => $infmap,
390 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
392 while ($cur_row_data = (
393 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
395 ( $_[1] and $rows_pos = -1 and $_[1]->() )
398 $cur_row_ids{0} = defined $cur_row_data->[0] ? $cur_row_data->[0] : "\0NULL\xFF$rows_pos\xFF0\0";
399 $cur_row_ids{1} = defined $cur_row_data->[1] ? $cur_row_data->[1] : "\0NULL\xFF$rows_pos\xFF1\0";
400 $cur_row_ids{5} = defined $cur_row_data->[5] ? $cur_row_data->[5] : "\0NULL\xFF$rows_pos\xFF5\0";
401 $cur_row_ids{6} = defined $cur_row_data->[6] ? $cur_row_data->[6] : "\0NULL\xFF$rows_pos\xFF6\0";
402 $cur_row_ids{8} = defined $cur_row_data->[8] ? $cur_row_data->[8] : "\0NULL\xFF$rows_pos\xFF8\0";
403 $cur_row_ids{10} = defined $cur_row_data->[10] ? $cur_row_data->[10] : "\0NULL\xFF$rows_pos\xFF10\0";
405 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
406 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last;
408 $collapse_idx[0]{$cur_row_ids{1}} ||= $_[0][$result_pos++] = [{ genreid => $cur_row_data->[4], latest_cd => $cur_row_data->[7], year => $cur_row_data->[3] }];
410 $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} ||= $collapse_idx[1]{$cur_row_ids{1}} = [];
411 $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}} = [];
412 $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }];
414 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
416 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
417 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} = [{ cdid => $cur_row_data->[6], genreid => $cur_row_data->[9], year => $cur_row_data->[2] }]
419 defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ );
421 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
423 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
424 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
426 defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ );
428 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
430 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
431 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
433 defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ );
435 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics} ||= $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} = [];
436 defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ );
438 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
440 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
441 $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} = [{ lyric_id => $cur_row_data->[10], text => $cur_row_data->[0] }]
445 $#{$_[0]} = $result_pos - 1;
447 'Multiple has_many on multiple branches torture test',
451 $schema->source ('CD')->_mk_row_parser({
452 inflate_map => $infmap,
456 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
458 while ($cur_row_data = (
459 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
461 ( $_[1] and $rows_pos = -1 and $_[1]->() )
464 $cur_row_ids{0} = defined $cur_row_data->[0] ? $cur_row_data->[0] : "\0NULL\xFF$rows_pos\xFF0\0";
465 $cur_row_ids{1} = defined $cur_row_data->[1] ? $cur_row_data->[1] : "\0NULL\xFF$rows_pos\xFF1\0";
466 $cur_row_ids{5} = defined $cur_row_data->[5] ? $cur_row_data->[5] : "\0NULL\xFF$rows_pos\xFF5\0";
467 $cur_row_ids{6} = defined $cur_row_data->[6] ? $cur_row_data->[6] : "\0NULL\xFF$rows_pos\xFF6\0";
468 $cur_row_ids{8} = defined $cur_row_data->[8] ? $cur_row_data->[8] : "\0NULL\xFF$rows_pos\xFF8\0";
469 $cur_row_ids{10} = defined $cur_row_data->[10] ? $cur_row_data->[10] : "\0NULL\xFF$rows_pos\xFF10\0";
471 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
472 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last;
474 $collapse_idx[0]{$cur_row_ids{1}} ||= $_[0][$result_pos++] = [{ genreid => $cur_row_data->[4], latest_cd => $cur_row_data->[7], year => $cur_row_data->[3] }];
476 $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} ||= $collapse_idx[1]{$cur_row_ids{1}} = [];
477 $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}} = [];
478 $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }];
480 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
482 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
483 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} = [{ cdid => $cur_row_data->[6], genreid => $cur_row_data->[9], year => $cur_row_data->[2] }]
485 defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ );
487 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
489 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
490 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
492 defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ );
494 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
496 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
497 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
499 defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ );
501 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics} ||= $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} = [];
502 defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ );
504 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
506 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
507 $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} = [{ lyric_id => $cur_row_data->[10], text => $cur_row_data->[0] }]
511 $#{$_[0]} = $result_pos - 1;
513 'Multiple has_many on multiple branches with branch torture test',
517 'single_track.trackid', # (0) definitive link to root from 1:1:1:1:M:M chain
518 'year', # (1) non-unique
519 'tracks.cd', # (2) \ together both uniqueness for second multirel
520 'tracks.title', # (3) / and definitive link back to root
521 'single_track.cd.artist.cds.cdid', # (4) to give uniquiness to ...tracks.title below
522 'single_track.cd.artist.cds.year', # (5) non-unique
523 'single_track.cd.artist.artistid', # (6) uniqufies entire parental chain
524 'single_track.cd.artist.cds.genreid', # (7) nullable
525 'single_track.cd.artist.cds.tracks.title',# (8) unique when combined with ...cds.cdid above
529 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
531 -identifying_columns => [],
532 -identifying_columns_variants => [
536 -identifying_columns => [ 0 ],
540 -identifying_columns => [ 0 ],
543 -identifying_columns => [ 0 ],
546 -identifying_columns => [ 0, 4 ],
549 -identifying_columns => [ 0, 4, 8 ],
557 -identifying_columns => [ 2, 3 ],
561 'Correct underdefined root collapse map constructed'
565 $schema->source ('CD')->_mk_row_parser({
566 inflate_map => $infmap,
570 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
572 while ($cur_row_data = (
573 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
575 ( $_[1] and $rows_pos = -1 and $_[1]->() )
578 $cur_row_ids{0} = defined $cur_row_data->[0] ? $cur_row_data->[0] : "\0NULL\xFF$rows_pos\xFF0\0";
579 $cur_row_ids{2} = defined $cur_row_data->[2] ? $cur_row_data->[2] : "\0NULL\xFF$rows_pos\xFF2\0";
580 $cur_row_ids{3} = defined $cur_row_data->[3] ? $cur_row_data->[3] : "\0NULL\xFF$rows_pos\xFF3\0";
581 $cur_row_ids{4} = defined $cur_row_data->[4] ? $cur_row_data->[4] : "\0NULL\xFF$rows_pos\xFF4\0";
582 $cur_row_ids{8} = defined $cur_row_data->[8] ? $cur_row_data->[8] : "\0NULL\xFF$rows_pos\xFF8\0";
584 # cache expensive set of ops in a non-existent rowid slot
586 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} ))
588 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} ))
593 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
594 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last;
596 $collapse_idx[0]{$cur_row_ids{10}} ||= $_[0][$result_pos++] = [{ year => $$cur_row_data[1] }];
598 $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track} ||= ($collapse_idx[1]{$cur_row_ids{0}} = [{ trackid => $cur_row_data->[0] }]);
599 defined($cur_row_data->[0]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track}, __NBC__ );
601 $collapse_idx[1]{$cur_row_ids{0}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{0}} = [];
603 $collapse_idx[2]{$cur_row_ids{0}}[1]{artist} ||= ($collapse_idx[3]{$cur_row_ids{0}} = [{ artistid => $cur_row_data->[6] }]);
605 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
607 push @{$collapse_idx[3]{$cur_row_ids{0}}[1]{cds}}, (
608 $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} = [{ cdid => $cur_row_data->[4], genreid => $cur_row_data->[7], year => $cur_row_data->[5] }]
610 defined($cur_row_data->[4]) or bless ( $collapse_idx[3]{$cur_row_ids{0}}[1]{cds}, __NBC__ );
612 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
614 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}}, (
615 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
617 defined($cur_row_data->[8]) or bless ( $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}, __NBC__ );
619 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
621 push @{$collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}}, (
622 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = [{ cd => $$cur_row_data[2], title => $cur_row_data->[3] }]
624 defined($cur_row_data->[2]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}, __NBC__ );
627 $#{$_[0]} = $result_pos - 1;
629 'Multiple has_many on multiple branches with underdefined root torture test',
633 $schema->source ('CD')->_mk_row_parser({
634 inflate_map => $infmap,
639 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
641 while ($cur_row_data = (
642 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
644 ( $_[1] and $rows_pos = -1 and $_[1]->() )
647 $cur_row_ids{0} = defined $cur_row_data->[0] ? $cur_row_data->[0] : "\0NULL\xFF$rows_pos\xFF0\0";
648 $cur_row_ids{2} = defined $cur_row_data->[2] ? $cur_row_data->[2] : "\0NULL\xFF$rows_pos\xFF2\0";
649 $cur_row_ids{3} = defined $cur_row_data->[3] ? $cur_row_data->[3] : "\0NULL\xFF$rows_pos\xFF3\0";
650 $cur_row_ids{4} = defined $cur_row_data->[4] ? $cur_row_data->[4] : "\0NULL\xFF$rows_pos\xFF4\0";
651 $cur_row_ids{8} = defined $cur_row_data->[8] ? $cur_row_data->[8] : "\0NULL\xFF$rows_pos\xFF8\0";
653 # cache expensive set of ops in a non-existent rowid slot
655 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} ))
657 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} ))
662 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
663 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last;
665 $collapse_idx[0]{$cur_row_ids{10}} ||= $_[0][$result_pos++] = { year => $$cur_row_data[1] };
667 (! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{10}}{single_track} = undef : do {
669 $collapse_idx[0]{$cur_row_ids{10}}{single_track} ||= ($collapse_idx[1]{$cur_row_ids{0}} = { trackid => $$cur_row_data[0] });
671 $collapse_idx[1]{$cur_row_ids{0}}{cd} ||= $collapse_idx[2]{$cur_row_ids{0}};
673 $collapse_idx[2]{$cur_row_ids{0}}{artist} ||= ($collapse_idx[3]{$cur_row_ids{0}} = { artistid => $$cur_row_data[6] });
675 (! defined $cur_row_data->[4] ) ? $collapse_idx[3]{$cur_row_ids{0}}{cds} = [] : do {
677 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
679 push @{$collapse_idx[3]{$cur_row_ids{0}}{cds}}, (
680 $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} = { cdid => $$cur_row_data[4], genreid => $$cur_row_data[7], year => $$cur_row_data[5] }
683 (! defined $cur_row_data->[8] ) ? $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks} = [] : do {
685 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
687 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks}}, (
688 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = { title => $$cur_row_data[8] }
694 (! defined $cur_row_data->[2] ) ? $collapse_idx[0]{$cur_row_ids{10}}{tracks} = [] : do {
695 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
697 push @{$collapse_idx[0]{$cur_row_ids{10}}{tracks}}, (
698 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = { cd => $$cur_row_data[2], title => $$cur_row_data[3] }
703 $#{$_[0]} = $result_pos - 1;
705 'Multiple has_many on multiple branches with underdefined root, HRI-direct torture test',
712 $deparser ||= B::Deparse->new;
713 local $Test::Builder::Level = $Test::Builder::Level + 1;
715 my ($got, $expect) = @_;
717 $expect =~ s/__NBC__/B::perlstring($DBIx::Class::ResultSource::RowParser::Util::null_branch_class)/ge;
719 $expect = " { use strict; use warnings FATAL => 'all';\n$expect\n }";
721 my @normalized = map {
722 my $cref = eval "sub { $_ }" or do {
723 fail "Coderef does not compile!\n\n$@\n\n$_";
726 $deparser->coderef2text($cref);
729 &is (@normalized, $_[2]||() ) or do {
730 eval { require Test::Differences }
731 ? &Test::Differences::eq_or_diff( @normalized, $_[2]||() )
732 : note ("Original sources:\n\n$got\n\n$expect\n")