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({
141 prune_null_branches => 1,
142 inflate_map => $infmap,
145 { artist => $_->[5], title => $_->[4], year => $_->[2] },
147 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) ) ? undef : [
154 { artistid => $_->[1] },
156 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) ? undef : [
159 tracks => ( ! defined $_->[0] ) ? undef : [
160 { title => $_->[0] },
172 '1:1 descending non-collapsing pruning parser terminating with chained 1:M:M',
176 ($schema->source ('CD')->_mk_row_parser({
178 prune_null_branches => 1,
179 inflate_map => $infmap,
182 artist => $_->[5], title => $_->[4], year => $_->[2],
184 ( single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
191 ( cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
195 ( tracks => ( ! defined $_->[0] )
197 : { title => $_->[0] }
206 '1:1 descending non-collapsing HRI-direct parser terminating with chained 1:M:M',
212 ($schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} })),
214 -identifying_columns => [ 4, 5 ],
217 -identifying_columns => [ 1, 4, 5 ],
222 -identifying_columns => [ 1, 4, 5 ],
226 -identifying_columns => [ 1, 4, 5 ],
230 -identifying_columns => [ 1, 3, 4, 5 ],
234 -identifying_columns => [ 0, 1, 3, 4, 5 ],
242 'Correct collapse map for 1:1 descending chain terminating with chained 1:M:M'
246 ($schema->source ('CD')->_mk_row_parser({
247 inflate_map => $infmap,
251 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
253 while ($cur_row_data = (
254 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
256 ( $_[1] and $rows_pos = -1 and $_[1]->() )
259 $cur_row_ids{0} = $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0";
260 $cur_row_ids{1} = $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0";
261 $cur_row_ids{3} = $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0";
262 $cur_row_ids{4} = $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0";
263 $cur_row_ids{5} = $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0";
265 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
266 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} and (unshift @{$_[2]}, $cur_row_data) and last;
268 # the rowdata itself for root node
269 $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] }];
271 # prefetch data of single_track (placed in root)
272 $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}} = [];
273 defined($cur_row_data->[1]) or bless( $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track}, __NBC__ );
275 # prefetch data of cd (placed in single_track)
276 $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}} = [];
278 # prefetch data of artist ( placed in single_track->cd)
279 $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] }];
281 # prefetch data of cds (if available)
282 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
284 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}}, (
285 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ cdid => $cur_row_data->[3] }]
287 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__ );
289 # prefetch data of tracks (if available)
290 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
292 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}}, (
293 $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] }]
295 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__ );
298 $#{$_[0]} = $result_pos - 1;
300 'Same 1:1 descending terminating with chained 1:M:M but with collapse',
304 ($schema->source ('CD')->_mk_row_parser({
305 inflate_map => $infmap,
308 prune_null_branches => 1,
311 my ($result_pos, @collapse_idx, $cur_row_data);
313 while ($cur_row_data = (
314 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
316 ( $_[1] and $rows_pos = -1 and $_[1]->() )
319 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
320 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]} and (unshift @{$_[2]}, $cur_row_data) and last;
322 # the rowdata itself for root node
323 $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] };
325 # prefetch data of single_track (placed in root)
326 (! defined($cur_row_data->[1]) ) ? $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]}{single_track} = undef : do {
327 $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]};
329 # prefetch data of cd (placed in single_track)
330 $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]};
332 # prefetch data of artist ( placed in single_track->cd)
333 $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] };
335 # prefetch data of cds (if available)
336 (! defined $cur_row_data->[3] ) ? $collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cds} = [] : do {
338 (! $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} )
340 push @{$collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cds}}, (
341 $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} = { cdid => $cur_row_data->[3] }
344 # prefetch data of tracks (if available)
345 ( ! 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 {
347 (! $collapse_idx[5]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} )
349 push @{$collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]}{tracks}}, (
350 $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] }
356 $#{$_[0]} = $result_pos - 1;
358 'Same 1:1 descending terminating with chained 1:M:M but with collapse, HRI-direct',
362 tracks.lyrics.existing_lyric_versions.text
363 existing_single_track.cd.artist.artistid
364 existing_single_track.cd.artist.cds.year
368 existing_single_track.cd.artist.cds.cdid
370 existing_single_track.cd.artist.cds.tracks.title
371 existing_single_track.cd.artist.cds.genreid
372 tracks.lyrics.existing_lyric_versions.lyric_id
376 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
378 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
380 existing_single_track => {
381 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
385 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
389 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
393 -identifying_columns => [ 1, 6 ], # existing_single_track.cd.artist.cds.cdid
397 -identifying_columns => [ 1, 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title
405 -identifying_columns => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title
409 -identifying_columns => [ 1, 5, 10 ], # existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id
413 existing_lyric_versions => {
414 -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
419 'Correct collapse map constructed',
423 ($schema->source ('CD')->_mk_row_parser({
424 inflate_map => $infmap,
428 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
430 while ($cur_row_data = (
431 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
433 ( $_[1] and $rows_pos = -1 and $_[1]->() )
436 $cur_row_ids{0} = $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0";
437 $cur_row_ids{1} = $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0";
438 $cur_row_ids{5} = $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0";
439 $cur_row_ids{6} = $cur_row_data->[6] // "\0NULL\xFF$rows_pos\xFF6\0";
440 $cur_row_ids{8} = $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0";
441 $cur_row_ids{10} = $cur_row_data->[10] // "\0NULL\xFF$rows_pos\xFF10\0";
443 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
444 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last;
446 $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] }];
448 $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_ids{1}} = [];
449 $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{1}} = [];
450 $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} //= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }];
452 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
454 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
455 $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] }]
457 defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ );
459 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
461 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
462 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
464 defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ );
466 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
468 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
469 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
471 defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ );
473 $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}} = [];
474 defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ );
476 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
478 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
479 $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] }]
483 $#{$_[0]} = $result_pos - 1;
485 'Multiple has_many on multiple branches torture test',
489 ($schema->source ('CD')->_mk_row_parser({
490 inflate_map => $infmap,
492 prune_null_branches => 1,
495 my ($result_pos, @collapse_idx, $cur_row_data);
497 while ($cur_row_data = (
498 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
500 ( $_[1] and $rows_pos = -1 and $_[1]->() )
503 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
504 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_data->[1]} and (unshift @{$_[2]}, $cur_row_data) and last;
506 $collapse_idx[0]{$cur_row_data->[1]} //= $_[0][$result_pos++] = [{ genreid => $cur_row_data->[4], latest_cd => $cur_row_data->[7], year => $cur_row_data->[3] }];
508 $collapse_idx[0]{$cur_row_data->[1]}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_data->[1]} = [];
509 $collapse_idx[1]{$cur_row_data->[1]}[1]{cd} //= $collapse_idx[2]{$cur_row_data->[1]} = [];
510 $collapse_idx[2]{$cur_row_data->[1]}[1]{artist} //= $collapse_idx[3]{$cur_row_data->[1]} = [{ artistid => $cur_row_data->[1] }];
512 (! defined($cur_row_data->[6])) ? $collapse_idx[3]{$cur_row_data->[1]}[1]{cds} = [] : do {
513 (! $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]} )
515 push @{ $collapse_idx[3]{$cur_row_data->[1]}[1]{cds} }, (
516 $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]} = [{ cdid => $cur_row_data->[6], genreid => $cur_row_data->[9], year => $cur_row_data->[2] }]
519 (! defined($cur_row_data->[8]) ) ? $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]}[1]{tracks} = [] : do {
521 (! $collapse_idx[5]{$cur_row_data->[1]}{$cur_row_data->[6]}{$cur_row_data->[8]} )
523 push @{ $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]}[1]{tracks} }, (
524 $collapse_idx[5]{$cur_row_data->[1]}{$cur_row_data->[6]}{$cur_row_data->[8]} = [{ title => $cur_row_data->[8] }]
529 (! defined($cur_row_data->[5]) ) ? $collapse_idx[0]{$cur_row_data->[1]}[1]{tracks} = [] : do {
531 (! $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]} )
533 push @{ $collapse_idx[0]{$cur_row_data->[1]}[1]{tracks} }, (
534 $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]} = [{ title => $cur_row_data->[5] }]
537 (! defined($cur_row_data->[10]) ) ? $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]}[1]{lyrics} = [] : do {
539 $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]}[1]{lyrics} //= $collapse_idx[7]{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]} = [];
541 (! $collapse_idx[8]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]} )
543 push @{ $collapse_idx[7]{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]}[1]{existing_lyric_versions} }, (
544 $collapse_idx[8]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]} = [{ lyric_id => $cur_row_data->[10], text => $cur_row_data->[0] }]
550 $#{$_[0]} = $result_pos - 1;
552 'Multiple has_many on multiple branches with branch pruning torture test',
556 'single_track.trackid', # (0) definitive link to root from 1:1:1:1:M:M chain
557 'year', # (1) non-unique
558 'tracks.cd', # (2) \ together both uniqueness for second multirel
559 'tracks.title', # (3) / and definitive link back to root
560 'single_track.cd.artist.cds.cdid', # (4) to give uniquiness to ...tracks.title below
561 'single_track.cd.artist.cds.year', # (5) non-unique
562 'single_track.cd.artist.artistid', # (6) uniqufies entire parental chain
563 'single_track.cd.artist.cds.genreid', # (7) nullable
564 'single_track.cd.artist.cds.tracks.title',# (8) unique when combined with ...cds.cdid above
568 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
570 -identifying_columns => [],
571 -identifying_columns_variants => [
575 -identifying_columns => [ 0 ],
579 -identifying_columns => [ 0 ],
582 -identifying_columns => [ 0 ],
585 -identifying_columns => [ 0, 4 ],
588 -identifying_columns => [ 0, 4, 8 ],
596 -identifying_columns => [ 2, 3 ],
600 'Correct underdefined root collapse map constructed'
604 ($schema->source ('CD')->_mk_row_parser({
605 inflate_map => $infmap,
609 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
611 while ($cur_row_data = (
612 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
614 ( $_[1] and $rows_pos = -1 and $_[1]->() )
617 $cur_row_ids{0} = $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0";
618 $cur_row_ids{2} = $cur_row_data->[2] // "\0NULL\xFF$rows_pos\xFF2\0";
619 $cur_row_ids{3} = $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0";
620 $cur_row_ids{4} = $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0";
621 $cur_row_ids{8} = $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0";
623 # cache expensive set of ops in a non-existent rowid slot
625 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} ))
627 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} ))
632 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
633 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last;
635 $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = [{ year => $$cur_row_data[1] }];
637 $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = [{ trackid => $cur_row_data->[0] }]);
638 defined($cur_row_data->[0]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track}, __NBC__ );
640 $collapse_idx[1]{$cur_row_ids{0}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{0}} = [];
642 $collapse_idx[2]{$cur_row_ids{0}}[1]{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = [{ artistid => $cur_row_data->[6] }]);
644 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
646 push @{$collapse_idx[3]{$cur_row_ids{0}}[1]{cds}}, (
647 $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] }]
649 defined($cur_row_data->[4]) or bless ( $collapse_idx[3]{$cur_row_ids{0}}[1]{cds}, __NBC__ );
651 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
653 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}}, (
654 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
656 defined($cur_row_data->[8]) or bless ( $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}, __NBC__ );
658 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
660 push @{$collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}}, (
661 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = [{ cd => $$cur_row_data[2], title => $cur_row_data->[3] }]
663 defined($cur_row_data->[2]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}, __NBC__ );
666 $#{$_[0]} = $result_pos - 1;
668 'Multiple has_many on multiple branches with underdefined root torture test',
672 ($schema->source ('CD')->_mk_row_parser({
673 inflate_map => $infmap,
676 prune_null_branches => 1,
679 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
681 while ($cur_row_data = (
682 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
684 ( $_[1] and $rows_pos = -1 and $_[1]->() )
687 # do not care about nullability here
688 $cur_row_ids{0} = $cur_row_data->[0];
689 $cur_row_ids{2} = $cur_row_data->[2];
690 $cur_row_ids{3} = $cur_row_data->[3];
691 $cur_row_ids{4} = $cur_row_data->[4];
692 $cur_row_ids{8} = $cur_row_data->[8];
694 # cache expensive set of ops in a non-existent rowid slot
696 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} ))
698 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} ))
703 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
704 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last;
706 $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = { year => $$cur_row_data[1] };
708 (! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{10}}{single_track} = undef : do {
710 $collapse_idx[0]{$cur_row_ids{10}}{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = { trackid => $$cur_row_data[0] });
712 $collapse_idx[1]{$cur_row_ids{0}}{cd} //= $collapse_idx[2]{$cur_row_ids{0}};
714 $collapse_idx[2]{$cur_row_ids{0}}{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = { artistid => $$cur_row_data[6] });
716 (! defined $cur_row_data->[4] ) ? $collapse_idx[3]{$cur_row_ids{0}}{cds} = [] : do {
718 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
720 push @{$collapse_idx[3]{$cur_row_ids{0}}{cds}}, (
721 $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] }
724 (! defined $cur_row_data->[8] ) ? $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks} = [] : do {
726 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
728 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks}}, (
729 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = { title => $$cur_row_data[8] }
735 (! defined $cur_row_data->[2] ) ? $collapse_idx[0]{$cur_row_ids{10}}{tracks} = [] : do {
736 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
738 push @{$collapse_idx[0]{$cur_row_ids{10}}{tracks}}, (
739 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = { cd => $$cur_row_data[2], title => $$cur_row_data[3] }
744 $#{$_[0]} = $result_pos - 1;
746 'Multiple has_many on multiple branches with underdefined root, HRI-direct torture test',
752 sub is_same_src { SKIP: {
753 $deparser ||= B::Deparse->new;
754 local $Test::Builder::Level = $Test::Builder::Level + 1;
756 my ($got, $expect) = @_;
758 skip "Not testing equality of source containing defined-or operator on this perl $]", 1
759 if ($] < 5.010 and$expect =~ m!\Q//=!);
761 $expect =~ s/__NBC__/B::perlstring($DBIx::Class::ResultSource::RowParser::Util::null_branch_class)/ge;
763 $expect = " { use strict; use warnings FATAL => 'all';\n$expect\n }";
765 my @normalized = map {
766 my $cref = eval "sub { $_ }" or do {
767 fail "Coderef does not compile!\n\n$@\n\n$_";
770 $deparser->coderef2text($cref);
773 &is (@normalized, $_[2]||() ) or do {
774 eval { require Test::Differences }
775 ? &Test::Differences::eq_or_diff( @normalized, $_[2]||() )
776 : note ("Original sources:\n\n$got\n\n$expect\n")