8 use DBIx::Class::_Util 'perlstring';
10 # globally set for the rest of test
11 # the rowparser maker does not order its hashes by default for the miniscule
12 # speed gain. But it does not disable sorting either - for this test
13 # everything will be ordered nicely, and the hash randomization of 5.18
14 # will not trip up anything
16 $Data::Dumper::Sortkeys = 1;
18 my $schema = DBICTest->init_schema(no_deploy => 1);
20 single_track.cd.artist.name
25 ($schema->source ('CD')->_mk_row_parser({
26 inflate_map => $infmap,
30 { single_track => ( ! defined( $_->[0]) )
51 'Simple 1:1 descending non-collapsing parser',
55 single_track.cd.artist.cds.tracks.title
56 single_track.cd.artist.artistid
58 single_track.cd.artist.cds.cdid
64 ($schema->source ('CD')->_mk_row_parser({
65 inflate_map => $infmap,
68 { artist => $_->[5], title => $_->[4], year => $_->[2] },
70 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
78 { artistid => $_->[1] },
80 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
84 tracks => ( ! defined $_->[0] )
85 ? bless ( [{ title => $_->[0] }], __NBC__ )
86 : [{ title => $_->[0] }]
92 tracks => ( ! defined $_->[0] )
93 ? bless ( [{ title => $_->[0] }], __NBC__ )
94 : [{ title => $_->[0] }]
110 { artistid => $_->[1] },
112 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
116 tracks => ( ! defined $_->[0] )
117 ? bless ( [{ title => $_->[0] }], __NBC__ )
118 : [{ title => $_->[0] }]
124 tracks => ( ! defined $_->[0] )
125 ? bless ( [{ title => $_->[0] }], __NBC__ )
126 : [{ title => $_->[0] }]
137 '1:1 descending non-collapsing parser terminating with chained 1:M:M',
141 ($schema->source ('CD')->_mk_row_parser({
142 prune_null_branches => 1,
143 inflate_map => $infmap,
146 { artist => $_->[5], title => $_->[4], year => $_->[2] },
148 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) ) ? undef : [
155 { artistid => $_->[1] },
157 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) ? undef : [
160 tracks => ( ! defined $_->[0] ) ? undef : [
161 { title => $_->[0] },
173 '1:1 descending non-collapsing pruning parser terminating with chained 1:M:M',
177 ($schema->source ('CD')->_mk_row_parser({
179 prune_null_branches => 1,
180 inflate_map => $infmap,
183 artist => $_->[5], title => $_->[4], year => $_->[2],
185 ( single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
192 ( cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
196 ( tracks => ( ! defined $_->[0] )
198 : { title => $_->[0] }
207 '1:1 descending non-collapsing HRI-direct parser terminating with chained 1:M:M',
213 ($schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} })),
215 -identifying_columns => [ 4, 5 ],
218 -identifying_columns => [ 1, 4, 5 ],
223 -identifying_columns => [ 1, 4, 5 ],
227 -identifying_columns => [ 1, 4, 5 ],
231 -identifying_columns => [ 1, 3, 4, 5 ],
235 -identifying_columns => [ 0, 1, 3, 4, 5 ],
243 'Correct collapse map for 1:1 descending chain terminating with chained 1:M:M'
247 ($schema->source ('CD')->_mk_row_parser({
248 inflate_map => $infmap,
252 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
254 while ($cur_row_data = (
261 ( ($rows_pos = -1), undef )
265 ( $_[1] and $_[1]->() )
268 @cur_row_ids{0,1,3,4,5} = (
269 ( $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0" ),
270 ( $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0" ),
271 ( $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0" ),
272 ( $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0" ),
273 ( $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0" ),
276 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
277 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} and (unshift @{$_[2]}, $cur_row_data) and last;
279 # the rowdata itself for root node
280 $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] }];
282 # prefetch data of single_track (placed in root)
283 $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}} = [];
284 defined($cur_row_data->[1]) or bless( $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track}, __NBC__ );
286 # prefetch data of cd (placed in single_track)
287 $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}} = [];
289 # prefetch data of artist ( placed in single_track->cd)
290 $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] }];
292 # prefetch data of cds (if available)
293 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
295 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}}, (
296 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ cdid => $cur_row_data->[3] }]
298 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__ );
300 # prefetch data of tracks (if available)
301 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
303 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}}, (
304 $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] }]
306 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__ );
309 $#{$_[0]} = $result_pos - 1;
311 'Same 1:1 descending terminating with chained 1:M:M but with collapse',
315 ($schema->source ('CD')->_mk_row_parser({
316 inflate_map => $infmap,
319 prune_null_branches => 1,
322 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
324 while ($cur_row_data = (
331 ( ($rows_pos = -1), undef )
335 ( $_[1] and $_[1]->() )
338 @cur_row_ids{0, 1, 3, 4, 5} = @{$cur_row_data}[0, 1, 3, 4, 5];
340 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
341 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} and (unshift @{$_[2]}, $cur_row_data) and last;
343 # the rowdata itself for root node
344 $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] };
346 # prefetch data of single_track (placed in root)
347 (! defined($cur_row_data->[1]) ) ? $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}{single_track} = undef : do {
348 $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}{single_track} //= $collapse_idx[1]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}};
350 # prefetch data of cd (placed in single_track)
351 $collapse_idx[1]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cd} //= $collapse_idx[2]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}};
353 # prefetch data of artist ( placed in single_track->cd)
354 $collapse_idx[2]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{artist} //= $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} = { artistid => $cur_row_data->[1] };
356 # prefetch data of cds (if available)
357 (! defined $cur_row_data->[3] ) ? $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cds} = [] : do {
359 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
361 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cds}}, (
362 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = { cdid => $cur_row_data->[3] }
365 # prefetch data of tracks (if available)
366 ( ! defined $cur_row_data->[0] ) ? $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}{tracks} = [] : do {
368 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
370 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}{tracks}}, (
371 $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] }
377 $#{$_[0]} = $result_pos - 1;
379 'Same 1:1 descending terminating with chained 1:M:M but with collapse, HRI-direct',
383 tracks.lyrics.existing_lyric_versions.text
384 existing_single_track.cd.artist.artistid
385 existing_single_track.cd.artist.cds.year
389 existing_single_track.cd.artist.cds.cdid
391 existing_single_track.cd.artist.cds.tracks.title
392 existing_single_track.cd.artist.cds.genreid
393 tracks.lyrics.existing_lyric_versions.lyric_id
397 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
399 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
401 existing_single_track => {
402 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
406 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
410 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
414 -identifying_columns => [ 1, 6 ], # existing_single_track.cd.artist.cds.cdid
418 -identifying_columns => [ 1, 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title
426 -identifying_columns => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title
430 -identifying_columns => [ 1, 5, 10 ], # existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id
434 existing_lyric_versions => {
435 -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
440 'Correct collapse map constructed',
444 ($schema->source ('CD')->_mk_row_parser({
445 inflate_map => $infmap,
449 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
451 while ($cur_row_data = (
458 ( ($rows_pos = -1), undef )
462 ( $_[1] and $_[1]->() )
465 @cur_row_ids{0, 1, 5, 6, 8, 10} = (
466 $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0",
467 $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0",
468 $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0",
469 $cur_row_data->[6] // "\0NULL\xFF$rows_pos\xFF6\0",
470 $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0",
471 $cur_row_data->[10] // "\0NULL\xFF$rows_pos\xFF10\0",
474 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
475 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last;
477 $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] }];
479 $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_ids{1}} = [];
480 $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{1}} = [];
481 $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} //= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }];
483 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
485 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
486 $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] }]
488 defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ );
490 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
492 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
493 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
495 defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ );
497 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
499 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
500 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
502 defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ );
504 $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}} = [];
505 defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ );
507 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
509 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
510 $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] }]
514 $#{$_[0]} = $result_pos - 1;
516 'Multiple has_many on multiple branches torture test',
520 ($schema->source ('CD')->_mk_row_parser({
521 inflate_map => $infmap,
523 prune_null_branches => 1,
526 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
528 while ($cur_row_data = (
535 ( ($rows_pos = -1), undef )
539 ( $_[1] and $_[1]->() )
542 @cur_row_ids{( 0, 1, 5, 6, 8, 10 )} = @{$cur_row_data}[( 0, 1, 5, 6, 8, 10 )];
544 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
545 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last;
547 $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] }];
549 $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_ids{1}} = [];
550 $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{1}} = [];
551 $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} //= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }];
553 (! defined($cur_row_data->[6])) ? $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} = [] : do {
554 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
556 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
557 $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] }]
560 (! defined($cur_row_data->[8]) ) ? $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} = [] : do {
562 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
564 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
565 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
570 (! defined($cur_row_data->[5]) ) ? $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} = [] : do {
572 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
574 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
575 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
578 (! defined($cur_row_data->[10]) ) ? $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics} = [] : do {
580 $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}} = [];
582 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
584 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
585 $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] }]
591 $#{$_[0]} = $result_pos - 1;
593 'Multiple has_many on multiple branches with branch pruning torture test',
597 'single_track.trackid', # (0) definitive link to root from 1:1:1:1:M:M chain
598 'year', # (1) non-unique
599 'tracks.cd', # (2) \ together both uniqueness for second multirel
600 'tracks.title', # (3) / and definitive link back to root
601 'single_track.cd.artist.cds.cdid', # (4) to give uniquiness to ...tracks.title below
602 'single_track.cd.artist.cds.year', # (5) non-unique
603 'single_track.cd.artist.artistid', # (6) uniqufies entire parental chain
604 'single_track.cd.artist.cds.genreid', # (7) nullable
605 'single_track.cd.artist.cds.tracks.title',# (8) unique when combined with ...cds.cdid above
609 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
611 -identifying_columns => [],
612 -identifying_columns_variants => [
616 -identifying_columns => [ 0 ],
620 -identifying_columns => [ 0 ],
623 -identifying_columns => [ 0 ],
626 -identifying_columns => [ 0, 4 ],
629 -identifying_columns => [ 0, 4, 8 ],
637 -identifying_columns => [ 2, 3 ],
641 'Correct underdefined root collapse map constructed'
645 ($schema->source ('CD')->_mk_row_parser({
646 inflate_map => $infmap,
650 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
652 while ($cur_row_data = (
659 ( ($rows_pos = -1), undef )
663 ( $_[1] and $_[1]->() )
666 @cur_row_ids{( 0, 2, 3, 4, 8 )} = (
667 $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0",
668 $cur_row_data->[2] // "\0NULL\xFF$rows_pos\xFF2\0",
669 $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0",
670 $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0",
671 $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0",
674 # cache expensive set of ops in a non-existent rowid slot
676 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_ids{0}, q{} ))
678 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_ids{2}, q{} ))
683 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
684 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last;
686 $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = [{ year => $$cur_row_data[1] }];
688 $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = [{ trackid => $cur_row_data->[0] }]);
689 defined($cur_row_data->[0]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track}, __NBC__ );
691 $collapse_idx[1]{$cur_row_ids{0}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{0}} = [];
693 $collapse_idx[2]{$cur_row_ids{0}}[1]{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = [{ artistid => $cur_row_data->[6] }]);
695 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
697 push @{$collapse_idx[3]{$cur_row_ids{0}}[1]{cds}}, (
698 $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] }]
700 defined($cur_row_data->[4]) or bless ( $collapse_idx[3]{$cur_row_ids{0}}[1]{cds}, __NBC__ );
702 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
704 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}}, (
705 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
707 defined($cur_row_data->[8]) or bless ( $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}, __NBC__ );
709 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
711 push @{$collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}}, (
712 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = [{ cd => $$cur_row_data[2], title => $cur_row_data->[3] }]
714 defined($cur_row_data->[2]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}, __NBC__ );
717 $#{$_[0]} = $result_pos - 1;
719 'Multiple has_many on multiple branches with underdefined root torture test',
723 ($schema->source ('CD')->_mk_row_parser({
724 inflate_map => $infmap,
727 prune_null_branches => 1,
730 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
732 while ($cur_row_data = (
739 ( ($rows_pos = -1), undef )
743 ( $_[1] and $_[1]->() )
746 # do not care about nullability here
747 @cur_row_ids{( 0, 2, 3, 4, 8 )} = @{$cur_row_data}[( 0, 2, 3, 4, 8 )];
749 # cache expensive set of ops in a non-existent rowid slot
751 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_ids{0}, q{} ))
753 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_ids{2}, q{} ))
758 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
759 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last;
761 $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = { year => $$cur_row_data[1] };
763 (! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{10}}{single_track} = undef : do {
765 $collapse_idx[0]{$cur_row_ids{10}}{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = { trackid => $$cur_row_data[0] });
767 $collapse_idx[1]{$cur_row_ids{0}}{cd} //= $collapse_idx[2]{$cur_row_ids{0}};
769 $collapse_idx[2]{$cur_row_ids{0}}{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = { artistid => $$cur_row_data[6] });
771 (! defined $cur_row_data->[4] ) ? $collapse_idx[3]{$cur_row_ids{0}}{cds} = [] : do {
773 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
775 push @{$collapse_idx[3]{$cur_row_ids{0}}{cds}}, (
776 $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] }
779 (! defined $cur_row_data->[8] ) ? $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks} = [] : do {
781 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
783 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks}}, (
784 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = { title => $$cur_row_data[8] }
790 (! defined $cur_row_data->[2] ) ? $collapse_idx[0]{$cur_row_ids{10}}{tracks} = [] : do {
791 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
793 push @{$collapse_idx[0]{$cur_row_ids{10}}{tracks}}, (
794 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = { cd => $$cur_row_data[2], title => $$cur_row_data[3] }
799 $#{$_[0]} = $result_pos - 1;
801 'Multiple has_many on multiple branches with underdefined root, HRI-direct torture test',
805 ($schema->source ('Owners')->_mk_row_parser({
806 inflate_map => [qw( books.title books.owner )],
808 prune_null_branches => 1,
811 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids );
813 while ($cur_row_data = (
820 ( ($rows_pos = -1), undef )
824 ( $_[1] and $_[1]->() )
827 @cur_row_ids{0,1} = @{$cur_row_data}[0,1];
830 ( ( defined $cur_row_data->[1] ) && (join "\xFF", q{}, $cur_row_ids{1}, q{} ))
835 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{3}} and (unshift @{$_[2]}, $cur_row_data) and last;
837 # empty data for the root node
838 $collapse_idx[0]{$cur_row_ids{3}} //= $_[0][$result_pos++] = [];
840 ( ! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{3}}[1]{"books"} = [] : do {
841 ( ! $collapse_idx[1]{$cur_row_ids{0}} )
843 push @{$collapse_idx[0]{$cur_row_ids{3}}[1]{books}},
844 $collapse_idx[1]{$cur_row_ids{0}} = [ { owner => $cur_row_data->[1], title => $cur_row_data->[0] } ]
848 $#{$_[0]} = $result_pos - 1; # truncate the passed in array to where we filled it with results
850 'Non-premultiplied implicit collapse with missing join columns',
856 sub is_same_src { SKIP: {
858 skip "Skipping comparison of unicode-posioned source", 1
859 if DBIx::Class::_ENV_::STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE;
861 $deparser ||= B::Deparse->new;
862 local $Test::Builder::Level = $Test::Builder::Level + 1;
864 my ($got, $expect) = @_;
866 skip "Not testing equality of source containing defined-or operator on this perl $]", 1
867 if ($] < 5.010 and$expect =~ m!\Q//=!);
869 $expect =~ s/__NBC__/perlstring($DBIx::Class::ResultSource::RowParser::Util::null_branch_class)/ge;
871 $expect = " { use strict; use warnings FATAL => 'uninitialized';\n$expect\n }";
873 my @normalized = map {
874 my $cref = eval "sub { $_ }" or do {
875 fail "Coderef does not compile!\n\n$@\n\n$_";
878 $deparser->coderef2text($cref);
881 &is (@normalized, $_[2]||() ) or do {
882 eval { require Test::Differences }
883 ? &Test::Differences::eq_or_diff( @normalized, $_[2]||() )
884 : note ("Original sources:\n\n$got\n\n$expect\n")