1 BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
10 use DBIx::Class::_Util 'perlstring';
12 # globally set for the rest of test
13 # the rowparser maker does not order its hashes by default for the miniscule
14 # speed gain. But it does not disable sorting either - for this test
15 # everything will be ordered nicely, and the hash randomization of 5.18
16 # will not trip up anything
18 $Data::Dumper::Sortkeys = 1;
20 my $schema = DBICTest->init_schema(no_deploy => 1);
22 single_track.cd.artist.name
27 ($schema->source ('CD')->_mk_row_parser({
28 inflate_map => $infmap,
32 { single_track => ( ! defined( $_->[0]) )
53 'Simple 1:1 descending non-collapsing parser',
57 single_track.cd.artist.cds.tracks.title
58 single_track.cd.artist.artistid
60 single_track.cd.artist.cds.cdid
66 ($schema->source ('CD')->_mk_row_parser({
67 inflate_map => $infmap,
70 { artist => $_->[5], title => $_->[4], year => $_->[2] },
72 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
80 { artistid => $_->[1] },
82 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
86 tracks => ( ! defined $_->[0] )
87 ? bless ( [{ title => $_->[0] }], __NBC__ )
88 : [{ title => $_->[0] }]
94 tracks => ( ! defined $_->[0] )
95 ? bless ( [{ title => $_->[0] }], __NBC__ )
96 : [{ title => $_->[0] }]
112 { artistid => $_->[1] },
114 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
118 tracks => ( ! defined $_->[0] )
119 ? bless ( [{ title => $_->[0] }], __NBC__ )
120 : [{ title => $_->[0] }]
126 tracks => ( ! defined $_->[0] )
127 ? bless ( [{ title => $_->[0] }], __NBC__ )
128 : [{ title => $_->[0] }]
139 '1:1 descending non-collapsing parser terminating with chained 1:M:M',
143 ($schema->source ('CD')->_mk_row_parser({
144 prune_null_branches => 1,
145 inflate_map => $infmap,
148 { artist => $_->[5], title => $_->[4], year => $_->[2] },
150 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) ) ? undef : [
157 { artistid => $_->[1] },
159 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) ? undef : [
162 tracks => ( ! defined $_->[0] ) ? undef : [
163 { title => $_->[0] },
175 '1:1 descending non-collapsing pruning parser terminating with chained 1:M:M',
179 ($schema->source ('CD')->_mk_row_parser({
181 prune_null_branches => 1,
182 inflate_map => $infmap,
185 artist => $_->[5], title => $_->[4], year => $_->[2],
187 ( single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
194 ( cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
198 ( tracks => ( ! defined $_->[0] )
200 : { title => $_->[0] }
209 '1:1 descending non-collapsing HRI-direct parser terminating with chained 1:M:M',
215 ($schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} })),
217 -identifying_columns => [ 4, 5 ],
220 -identifying_columns => [ 1, 4, 5 ],
225 -identifying_columns => [ 1, 4, 5 ],
229 -identifying_columns => [ 1, 4, 5 ],
233 -identifying_columns => [ 1, 3, 4, 5 ],
237 -identifying_columns => [ 0, 1, 3, 4, 5 ],
245 'Correct collapse map for 1:1 descending chain terminating with chained 1:M:M'
249 ($schema->source ('CD')->_mk_row_parser({
250 inflate_map => $infmap,
254 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
256 while ($cur_row_data = (
263 ( ($rows_pos = -1), undef )
267 ( $_[1] and $_[1]->() )
270 ( @cur_row_ids{0,1,3,4,5} = (
271 ( $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0" ),
272 ( $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0" ),
273 ( $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0" ),
274 ( $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0" ),
275 ( $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0" ),
278 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
279 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} and (unshift @{$_[2]}, $cur_row_data) and last ),
281 # the rowdata itself for root node
282 ( $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] }] ),
284 # prefetch data of single_track (placed in root)
285 ( $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}} = [] ),
286 ( defined($cur_row_data->[1]) or bless( $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track}, __NBC__ ) ),
288 # prefetch data of cd (placed in single_track)
289 ( $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}} = [] ),
291 # prefetch data of artist ( placed in single_track->cd)
292 ( $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] }] ),
294 # prefetch data of cds (if available)
296 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
298 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}}, (
299 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ cdid => $cur_row_data->[3] }]
302 ( 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__ ) ),
304 # prefetch data of tracks (if available)
306 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
308 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}}, (
309 $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] }]
312 ( 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__ ) ),
315 $#{$_[0]} = $result_pos - 1;
317 'Same 1:1 descending terminating with chained 1:M:M but with collapse',
321 ($schema->source ('CD')->_mk_row_parser({
322 inflate_map => $infmap,
325 prune_null_branches => 1,
328 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
330 while ($cur_row_data = (
337 ( ($rows_pos = -1), undef )
341 ( $_[1] and $_[1]->() )
344 ( @cur_row_ids{0, 1, 3, 4, 5} = @{$cur_row_data}[0, 1, 3, 4, 5] ),
346 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
347 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} and (unshift @{$_[2]}, $cur_row_data) and last ),
349 # the rowdata itself for root node
350 ( $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] } ),
352 # prefetch data of single_track (placed in root)
353 ( (! defined($cur_row_data->[1]) ) ? $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}{single_track} = undef : do {
354 ( $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}} ),
356 # prefetch data of cd (placed in single_track)
357 ( $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}} ),
359 # prefetch data of artist ( placed in single_track->cd)
360 ( $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] } ),
362 # prefetch data of cds (if available)
363 ( (! defined $cur_row_data->[3] ) ? $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cds} = [] : do {
366 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
368 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cds}}, (
369 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = { cdid => $cur_row_data->[3] }
373 # prefetch data of tracks (if available)
374 (( ! 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 {
377 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
379 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}{tracks}}, (
380 $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] }
387 $#{$_[0]} = $result_pos - 1;
389 'Same 1:1 descending terminating with chained 1:M:M but with collapse, HRI-direct',
393 tracks.lyrics.existing_lyric_versions.text
394 existing_single_track.cd.artist.artistid
395 existing_single_track.cd.artist.cds.year
399 existing_single_track.cd.artist.cds.cdid
401 existing_single_track.cd.artist.cds.tracks.title
402 existing_single_track.cd.artist.cds.genreid
403 tracks.lyrics.existing_lyric_versions.lyric_id
407 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
409 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
411 existing_single_track => {
412 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
416 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
420 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
424 -identifying_columns => [ 1, 6 ], # existing_single_track.cd.artist.cds.cdid
428 -identifying_columns => [ 1, 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title
436 -identifying_columns => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title
440 -identifying_columns => [ 1, 5, 10 ], # existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id
444 existing_lyric_versions => {
445 -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
450 'Correct collapse map constructed',
454 ($schema->source ('CD')->_mk_row_parser({
455 inflate_map => $infmap,
459 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
461 while ($cur_row_data = (
468 ( ($rows_pos = -1), undef )
472 ( $_[1] and $_[1]->() )
475 ( @cur_row_ids{0, 1, 5, 6, 8, 10} = (
476 $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0",
477 $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0",
478 $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0",
479 $cur_row_data->[6] // "\0NULL\xFF$rows_pos\xFF6\0",
480 $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0",
481 $cur_row_data->[10] // "\0NULL\xFF$rows_pos\xFF10\0",
484 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
485 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last ),
487 ( $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] }] ),
489 ( $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_ids{1}} = [] ),
490 ( $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{1}} = [] ),
491 ( $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} //= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }] ),
494 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
496 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
497 $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] }]
500 ( defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ ) ),
503 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
505 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
506 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
509 ( defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ ) ),
512 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
514 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
515 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
518 ( defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ ) ),
520 ( $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}} = [] ),
521 ( defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ ) ),
524 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
526 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
527 $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] }]
532 $#{$_[0]} = $result_pos - 1;
534 'Multiple has_many on multiple branches torture test',
538 ($schema->source ('CD')->_mk_row_parser({
539 inflate_map => $infmap,
541 prune_null_branches => 1,
544 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
546 while ($cur_row_data = (
553 ( ($rows_pos = -1), undef )
557 ( $_[1] and $_[1]->() )
560 ( @cur_row_ids{( 0, 1, 5, 6, 8, 10 )} = @{$cur_row_data}[( 0, 1, 5, 6, 8, 10 )] ),
562 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
563 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last ),
565 ( $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] }] ),
567 ( $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_ids{1}} = [] ),
568 ( $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{1}} = [] ),
569 ( $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} //= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }] ),
571 ( (! defined($cur_row_data->[6])) ? $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} = [] : do {
573 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
575 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
576 $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] }]
580 ( (! defined($cur_row_data->[8]) ) ? $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} = [] : do {
582 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
584 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
585 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
591 ( (! defined($cur_row_data->[5]) ) ? $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} = [] : do {
594 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
596 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
597 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
601 ( (! defined($cur_row_data->[10]) ) ? $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics} = [] : do {
603 ( $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}} = [] ),
606 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
608 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
609 $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] }]
616 $#{$_[0]} = $result_pos - 1;
618 'Multiple has_many on multiple branches with branch pruning torture test',
622 'single_track.trackid', # (0) definitive link to root from 1:1:1:1:M:M chain
623 'year', # (1) non-unique
624 'tracks.cd', # (2) \ together both uniqueness for second multirel
625 'tracks.title', # (3) / and definitive link back to root
626 'single_track.cd.artist.cds.cdid', # (4) to give uniquiness to ...tracks.title below
627 'single_track.cd.artist.cds.year', # (5) non-unique
628 'single_track.cd.artist.artistid', # (6) uniqufies entire parental chain
629 'single_track.cd.artist.cds.genreid', # (7) nullable
630 'single_track.cd.artist.cds.tracks.title',# (8) unique when combined with ...cds.cdid above
634 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
636 -identifying_columns => [],
637 -identifying_columns_variants => [
641 -identifying_columns => [ 0 ],
645 -identifying_columns => [ 0 ],
648 -identifying_columns => [ 0 ],
651 -identifying_columns => [ 0, 4 ],
654 -identifying_columns => [ 0, 4, 8 ],
662 -identifying_columns => [ 2, 3 ],
666 'Correct underdefined root collapse map constructed'
670 ($schema->source ('CD')->_mk_row_parser({
671 inflate_map => $infmap,
675 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
677 while ($cur_row_data = (
684 ( ($rows_pos = -1), undef )
688 ( $_[1] and $_[1]->() )
691 ( @cur_row_ids{( 0, 2, 3, 4, 8 )} = (
692 $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0",
693 $cur_row_data->[2] // "\0NULL\xFF$rows_pos\xFF2\0",
694 $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0",
695 $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0",
696 $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0",
699 # cache expensive set of ops in a non-existent rowid slot
700 ( $cur_row_ids{10} = (
701 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_ids{0}, q{} ))
703 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_ids{2}, q{} ))
708 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
709 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last ),
711 ( $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = [{ year => $$cur_row_data[1] }] ),
713 ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = [{ trackid => $cur_row_data->[0] }]) ),
714 ( defined($cur_row_data->[0]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track}, __NBC__ ) ),
716 ( $collapse_idx[1]{$cur_row_ids{0}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{0}} = [] ),
718 ( $collapse_idx[2]{$cur_row_ids{0}}[1]{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = [{ artistid => $cur_row_data->[6] }]) ),
721 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
723 push @{$collapse_idx[3]{$cur_row_ids{0}}[1]{cds}}, (
724 $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] }]
727 ( defined($cur_row_data->[4]) or bless ( $collapse_idx[3]{$cur_row_ids{0}}[1]{cds}, __NBC__ ) ),
730 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
732 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}}, (
733 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
736 ( defined($cur_row_data->[8]) or bless ( $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}, __NBC__ ) ),
739 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
741 push @{$collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}}, (
742 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = [{ cd => $$cur_row_data[2], title => $cur_row_data->[3] }]
745 ( defined($cur_row_data->[2]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}, __NBC__ ) ),
748 $#{$_[0]} = $result_pos - 1;
750 'Multiple has_many on multiple branches with underdefined root torture test',
754 ($schema->source ('CD')->_mk_row_parser({
755 inflate_map => $infmap,
758 prune_null_branches => 1,
761 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
763 while ($cur_row_data = (
770 ( ($rows_pos = -1), undef )
774 ( $_[1] and $_[1]->() )
777 # do not care about nullability here
778 ( @cur_row_ids{( 0, 2, 3, 4, 8 )} = @{$cur_row_data}[( 0, 2, 3, 4, 8 )] ),
780 # cache expensive set of ops in a non-existent rowid slot
781 ( $cur_row_ids{10} = (
782 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_ids{0}, q{} ))
784 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_ids{2}, q{} ))
789 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
790 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last ),
792 ( $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = { year => $$cur_row_data[1] } ),
794 ( (! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{10}}{single_track} = undef : do {
796 ( $collapse_idx[0]{$cur_row_ids{10}}{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = { trackid => $$cur_row_data[0] }) ),
798 ( $collapse_idx[1]{$cur_row_ids{0}}{cd} //= $collapse_idx[2]{$cur_row_ids{0}} ),
800 ( $collapse_idx[2]{$cur_row_ids{0}}{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = { artistid => $$cur_row_data[6] }) ),
802 ( (! defined $cur_row_data->[4] ) ? $collapse_idx[3]{$cur_row_ids{0}}{cds} = [] : do {
805 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
807 push @{$collapse_idx[3]{$cur_row_ids{0}}{cds}}, (
808 $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] }
812 ( (! defined $cur_row_data->[8] ) ? $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks} = [] : do {
814 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
816 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks}}, (
817 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = { title => $$cur_row_data[8] }
823 ( (! defined $cur_row_data->[2] ) ? $collapse_idx[0]{$cur_row_ids{10}}{tracks} = [] : do {
825 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
827 push @{$collapse_idx[0]{$cur_row_ids{10}}{tracks}}, (
828 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = { cd => $$cur_row_data[2], title => $$cur_row_data[3] }
834 $#{$_[0]} = $result_pos - 1;
836 'Multiple has_many on multiple branches with underdefined root, HRI-direct torture test',
840 ($schema->source ('Owners')->_mk_row_parser({
841 inflate_map => [qw( books.title books.owner )],
843 prune_null_branches => 1,
846 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids );
848 while ($cur_row_data = (
855 ( ($rows_pos = -1), undef )
859 ( $_[1] and $_[1]->() )
862 ( @cur_row_ids{0,1} = @{$cur_row_data}[0,1] ),
864 ( $cur_row_ids{3} = (
865 ( ( defined $cur_row_data->[1] ) && (join "\xFF", q{}, $cur_row_ids{1}, q{} ))
870 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{3}} and (unshift @{$_[2]}, $cur_row_data) and last ),
872 # empty data for the root node
873 ( $collapse_idx[0]{$cur_row_ids{3}} //= $_[0][$result_pos++] = [] ),
875 ( ( ! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{3}}[1]{"books"} = [] : do {
876 ( ! $collapse_idx[1]{$cur_row_ids{0}} )
878 push @{$collapse_idx[0]{$cur_row_ids{3}}[1]{books}},
879 $collapse_idx[1]{$cur_row_ids{0}} = [ { owner => $cur_row_data->[1], title => $cur_row_data->[0] } ]
883 $#{$_[0]} = $result_pos - 1; # truncate the passed in array to where we filled it with results
885 'Non-premultiplied implicit collapse with missing join columns',
891 sub is_same_src { SKIP: {
893 skip "Skipping comparison of unicode-posioned source", 1
894 if DBIx::Class::_ENV_::STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE;
896 $deparser ||= B::Deparse->new;
897 local $Test::Builder::Level = $Test::Builder::Level + 1;
899 my ($got, $expect) = @_;
901 skip "Not testing equality of source containing defined-or operator on this perl $]", 1
902 if ( "$]" < 5.010 and $expect =~ m!\Q//=! );
904 $expect =~ s/__NBC__/perlstring($DBIx::Class::ResultSource::RowParser::Util::null_branch_class)/ge;
906 $expect = " { use strict; use warnings FATAL => 'uninitialized';\n$expect\n }";
908 my @normalized = map {
909 my $cref = eval "sub { $_ }" or do {
910 fail "Coderef does not compile!\n\n$@\n\n$_";
913 $deparser->coderef2text($cref);
916 &is (@normalized, $_[2]||() ) or do {
917 eval { require Test::Differences }
918 ? &Test::Differences::eq_or_diff( @normalized, $_[2]||() )
919 : note ("Original sources:\n\n$got\n\n$expect\n")