1 BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
10 use DBIx::Class::_Util 'perlstring';
12 my $schema = DBICTest->init_schema(no_deploy => 1);
14 single_track.cd.artist.name
19 ($schema->source ('CD')->_mk_row_parser({
20 inflate_map => $infmap,
24 { single_track => ( ! defined( $_->[0]) )
45 'Simple 1:1 descending non-collapsing parser',
49 single_track.cd.artist.cds.tracks.title
50 single_track.cd.artist.artistid
52 single_track.cd.artist.cds.cdid
58 ($schema->source ('CD')->_mk_row_parser({
59 inflate_map => $infmap,
62 { artist => $_->[5], title => $_->[4], year => $_->[2] },
64 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
72 { artistid => $_->[1] },
74 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
78 tracks => ( ! defined $_->[0] )
79 ? bless ( [{ title => $_->[0] }], __NBC__ )
80 : [{ title => $_->[0] }]
86 tracks => ( ! defined $_->[0] )
87 ? bless ( [{ title => $_->[0] }], __NBC__ )
88 : [{ title => $_->[0] }]
104 { artistid => $_->[1] },
106 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
110 tracks => ( ! defined $_->[0] )
111 ? bless ( [{ title => $_->[0] }], __NBC__ )
112 : [{ title => $_->[0] }]
118 tracks => ( ! defined $_->[0] )
119 ? bless ( [{ title => $_->[0] }], __NBC__ )
120 : [{ title => $_->[0] }]
131 '1:1 descending non-collapsing parser terminating with chained 1:M:M',
135 ($schema->source ('CD')->_mk_row_parser({
136 prune_null_branches => 1,
137 inflate_map => $infmap,
140 { artist => $_->[5], title => $_->[4], year => $_->[2] },
142 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) ) ? undef : [
149 { artistid => $_->[1] },
151 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) ? undef : [
154 tracks => ( ! defined $_->[0] ) ? undef : [
155 { title => $_->[0] },
167 '1:1 descending non-collapsing pruning parser terminating with chained 1:M:M',
171 ($schema->source ('CD')->_mk_row_parser({
173 prune_null_branches => 1,
174 inflate_map => $infmap,
177 artist => $_->[5], title => $_->[4], year => $_->[2],
179 ( single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
186 ( cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
190 ( tracks => ( ! defined $_->[0] )
192 : { title => $_->[0] }
201 '1:1 descending non-collapsing HRI-direct parser terminating with chained 1:M:M',
207 ($schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} })),
209 -identifying_columns => [ 4, 5 ],
212 -identifying_columns => [ 1, 4, 5 ],
217 -identifying_columns => [ 1, 4, 5 ],
221 -identifying_columns => [ 1, 4, 5 ],
225 -identifying_columns => [ 1, 3, 4, 5 ],
229 -identifying_columns => [ 0, 1, 3, 4, 5 ],
237 'Correct collapse map for 1:1 descending chain terminating with chained 1:M:M'
241 ($schema->source ('CD')->_mk_row_parser({
242 inflate_map => $infmap,
246 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
248 while ($cur_row_data = (
255 ( ($rows_pos = -1), undef )
259 ( $_[1] and $_[1]->() )
262 ( @cur_row_ids{0,1,3,4,5} = (
263 ( $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0" ),
264 ( $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0" ),
265 ( $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0" ),
266 ( $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0" ),
267 ( $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0" ),
270 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
271 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} and (unshift @{$_[2]}, $cur_row_data) and last ),
273 # the rowdata itself for root node
274 ( $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] }] ),
276 # prefetch data of single_track (placed in root)
277 ( $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}} = [] ),
278 ( defined($cur_row_data->[1]) or bless( $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track}, __NBC__ ) ),
280 # prefetch data of cd (placed in single_track)
281 ( $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}} = [] ),
283 # prefetch data of artist ( placed in single_track->cd)
284 ( $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] }] ),
286 # prefetch data of cds (if available)
288 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
290 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}}, (
291 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ cdid => $cur_row_data->[3] }]
294 ( 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__ ) ),
296 # prefetch data of tracks (if available)
298 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
300 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}}, (
301 $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] }]
304 ( 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__ ) ),
307 $#{$_[0]} = $result_pos - 1;
309 'Same 1:1 descending terminating with chained 1:M:M but with collapse',
313 ($schema->source ('CD')->_mk_row_parser({
314 inflate_map => $infmap,
317 prune_null_branches => 1,
320 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
322 while ($cur_row_data = (
329 ( ($rows_pos = -1), undef )
333 ( $_[1] and $_[1]->() )
336 ( @cur_row_ids{0, 1, 3, 4, 5} = @{$cur_row_data}[0, 1, 3, 4, 5] ),
338 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
339 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} and (unshift @{$_[2]}, $cur_row_data) and last ),
341 # the rowdata itself for root node
342 ( $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] } ),
344 # prefetch data of single_track (placed in root)
345 ( (! defined($cur_row_data->[1]) ) ? $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}{single_track} = undef : do {
346 ( $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}} = {} ),
348 # prefetch data of cd (placed in single_track)
349 ( $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}} = {} ),
351 # prefetch data of artist ( placed in single_track->cd)
352 ( $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] } ),
354 # prefetch data of cds (if available)
355 ( (! defined $cur_row_data->[3] ) ? $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cds} = [] : do {
358 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
360 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cds}}, (
361 $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 {
369 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
371 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}{tracks}}, (
372 $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] }
379 $#{$_[0]} = $result_pos - 1;
381 'Same 1:1 descending terminating with chained 1:M:M but with collapse, HRI-direct',
385 tracks.lyrics.existing_lyric_versions.text
386 existing_single_track.cd.artist.artistid
387 existing_single_track.cd.artist.cds.year
391 existing_single_track.cd.artist.cds.cdid
393 existing_single_track.cd.artist.cds.tracks.title
394 existing_single_track.cd.artist.cds.genreid
395 tracks.lyrics.existing_lyric_versions.lyric_id
399 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
401 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
403 existing_single_track => {
404 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
408 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
412 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
416 -identifying_columns => [ 1, 6 ], # existing_single_track.cd.artist.cds.cdid
420 -identifying_columns => [ 1, 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title
428 -identifying_columns => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title
432 -identifying_columns => [ 1, 5, 10 ], # existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id
436 existing_lyric_versions => {
437 -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
442 'Correct collapse map constructed',
446 ($schema->source ('CD')->_mk_row_parser({
447 inflate_map => $infmap,
451 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
453 while ($cur_row_data = (
460 ( ($rows_pos = -1), undef )
464 ( $_[1] and $_[1]->() )
467 ( @cur_row_ids{0, 1, 5, 6, 8, 10} = (
468 $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0",
469 $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0",
470 $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0",
471 $cur_row_data->[6] // "\0NULL\xFF$rows_pos\xFF6\0",
472 $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0",
473 $cur_row_data->[10] // "\0NULL\xFF$rows_pos\xFF10\0",
476 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
477 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last ),
479 ( $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] }] ),
481 ( $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_ids{1}} = [] ),
482 ( $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{1}} = [] ),
483 ( $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} //= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }] ),
486 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
488 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
489 $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] }]
492 ( defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ ) ),
495 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
497 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
498 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
501 ( defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ ) ),
504 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
506 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
507 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
510 ( defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ ) ),
512 ( $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}} = [] ),
513 ( defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ ) ),
516 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
518 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
519 $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] }]
524 $#{$_[0]} = $result_pos - 1;
526 'Multiple has_many on multiple branches torture test',
530 ($schema->source ('CD')->_mk_row_parser({
531 inflate_map => $infmap,
533 prune_null_branches => 1,
536 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
538 while ($cur_row_data = (
545 ( ($rows_pos = -1), undef )
549 ( $_[1] and $_[1]->() )
552 ( @cur_row_ids{( 0, 1, 5, 6, 8, 10 )} = @{$cur_row_data}[( 0, 1, 5, 6, 8, 10 )] ),
554 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
555 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last ),
557 ( $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] }] ),
559 ( $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_ids{1}} = [] ),
560 ( $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{1}} = [] ),
561 ( $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} //= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }] ),
563 ( (! defined($cur_row_data->[6])) ? $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} = [] : do {
565 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
567 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
568 $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] }]
572 ( (! defined($cur_row_data->[8]) ) ? $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} = [] : do {
574 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
576 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
577 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
583 ( (! defined($cur_row_data->[5]) ) ? $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} = [] : do {
586 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
588 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
589 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
593 ( (! defined($cur_row_data->[10]) ) ? $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics} = [] : do {
595 ( $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}} = [] ),
598 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
600 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
601 $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] }]
608 $#{$_[0]} = $result_pos - 1;
610 'Multiple has_many on multiple branches with branch pruning torture test',
614 'single_track.trackid', # (0) definitive link to root from 1:1:1:1:M:M chain
615 'year', # (1) non-unique
616 'tracks.cd', # (2) \ together both uniqueness for second multirel
617 'tracks.title', # (3) / and definitive link back to root
618 'single_track.cd.artist.cds.cdid', # (4) to give uniquiness to ...tracks.title below
619 'single_track.cd.artist.cds.year', # (5) non-unique
620 'single_track.cd.artist.artistid', # (6) uniqufies entire parental chain
621 'single_track.cd.artist.cds.genreid', # (7) nullable
622 'single_track.cd.artist.cds.tracks.title',# (8) unique when combined with ...cds.cdid above
626 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
628 -identifying_columns => [],
629 -identifying_columns_variants => [
633 -identifying_columns => [ 0 ],
637 -identifying_columns => [ 0 ],
640 -identifying_columns => [ 0 ],
643 -identifying_columns => [ 0, 4 ],
646 -identifying_columns => [ 0, 4, 8 ],
654 -identifying_columns => [ 2, 3 ],
658 'Correct underdefined root collapse map constructed'
662 ($schema->source ('CD')->_mk_row_parser({
663 inflate_map => $infmap,
667 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
669 while ($cur_row_data = (
676 ( ($rows_pos = -1), undef )
680 ( $_[1] and $_[1]->() )
683 ( @cur_row_ids{( 0, 2, 3, 4, 8 )} = (
684 $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0",
685 $cur_row_data->[2] // "\0NULL\xFF$rows_pos\xFF2\0",
686 $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0",
687 $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0",
688 $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0",
691 # cache expensive set of ops in a non-existent rowid slot
692 ( $cur_row_ids{10} = (
693 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_ids{0}, q{} ))
695 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_ids{2}, q{} ))
700 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
701 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last ),
703 ( $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = [{ year => $$cur_row_data[1] }] ),
705 ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = [{ trackid => $cur_row_data->[0] }]) ),
706 ( defined($cur_row_data->[0]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track}, __NBC__ ) ),
708 ( $collapse_idx[1]{$cur_row_ids{0}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{0}} = [] ),
710 ( $collapse_idx[2]{$cur_row_ids{0}}[1]{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = [{ artistid => $cur_row_data->[6] }]) ),
713 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
715 push @{$collapse_idx[3]{$cur_row_ids{0}}[1]{cds}}, (
716 $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] }]
719 ( defined($cur_row_data->[4]) or bless ( $collapse_idx[3]{$cur_row_ids{0}}[1]{cds}, __NBC__ ) ),
722 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
724 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}}, (
725 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
728 ( defined($cur_row_data->[8]) or bless ( $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}, __NBC__ ) ),
731 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
733 push @{$collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}}, (
734 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = [{ cd => $$cur_row_data[2], title => $cur_row_data->[3] }]
737 ( defined($cur_row_data->[2]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}, __NBC__ ) ),
740 $#{$_[0]} = $result_pos - 1;
742 'Multiple has_many on multiple branches with underdefined root torture test',
746 ($schema->source ('CD')->_mk_row_parser({
747 inflate_map => $infmap,
750 prune_null_branches => 1,
753 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
755 while ($cur_row_data = (
762 ( ($rows_pos = -1), undef )
766 ( $_[1] and $_[1]->() )
769 # do not care about nullability here
770 ( @cur_row_ids{( 0, 2, 3, 4, 8 )} = @{$cur_row_data}[( 0, 2, 3, 4, 8 )] ),
772 # cache expensive set of ops in a non-existent rowid slot
773 ( $cur_row_ids{10} = (
774 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_ids{0}, q{} ))
776 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_ids{2}, q{} ))
781 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
782 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last ),
784 ( $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = { year => $$cur_row_data[1] } ),
786 ( (! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{10}}{single_track} = undef : do {
788 ( $collapse_idx[0]{$cur_row_ids{10}}{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = { trackid => $$cur_row_data[0] }) ),
790 ( $collapse_idx[1]{$cur_row_ids{0}}{cd} //= $collapse_idx[2]{$cur_row_ids{0}} = {} ),
792 ( $collapse_idx[2]{$cur_row_ids{0}}{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = { artistid => $$cur_row_data[6] }) ),
794 ( (! defined $cur_row_data->[4] ) ? $collapse_idx[3]{$cur_row_ids{0}}{cds} = [] : do {
797 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
799 push @{$collapse_idx[3]{$cur_row_ids{0}}{cds}}, (
800 $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] }
804 ( (! defined $cur_row_data->[8] ) ? $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks} = [] : do {
806 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
808 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks}}, (
809 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = { title => $$cur_row_data[8] }
815 ( (! defined $cur_row_data->[2] ) ? $collapse_idx[0]{$cur_row_ids{10}}{tracks} = [] : do {
817 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
819 push @{$collapse_idx[0]{$cur_row_ids{10}}{tracks}}, (
820 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = { cd => $$cur_row_data[2], title => $$cur_row_data[3] }
826 $#{$_[0]} = $result_pos - 1;
828 'Multiple has_many on multiple branches with underdefined root, HRI-direct torture test',
832 ($schema->source ('Owners')->_mk_row_parser({
833 inflate_map => [qw( books.title books.owner )],
835 prune_null_branches => 1,
838 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids );
840 while ($cur_row_data = (
847 ( ($rows_pos = -1), undef )
851 ( $_[1] and $_[1]->() )
854 ( @cur_row_ids{0,1} = @{$cur_row_data}[0,1] ),
856 ( $cur_row_ids{3} = (
857 ( ( defined $cur_row_data->[1] ) && (join "\xFF", q{}, $cur_row_ids{1}, q{} ))
862 ( $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{3}} and (unshift @{$_[2]}, $cur_row_data) and last ),
864 # empty data for the root node
865 ( $collapse_idx[0]{$cur_row_ids{3}} //= $_[0][$result_pos++] = [] ),
867 ( ( ! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{3}}[1]{"books"} = [] : do {
868 ( ! $collapse_idx[1]{$cur_row_ids{0}} )
870 push @{$collapse_idx[0]{$cur_row_ids{3}}[1]{books}},
871 $collapse_idx[1]{$cur_row_ids{0}} = [ { owner => $cur_row_data->[1], title => $cur_row_data->[0] } ]
875 $#{$_[0]} = $result_pos - 1; # truncate the passed in array to where we filled it with results
877 'Non-premultiplied implicit collapse with missing join columns',
883 sub is_same_src { SKIP: {
885 skip "Skipping comparison of unicode-poisoned source", 1
886 if DBIx::Class::_ENV_::STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE;
888 $deparser ||= B::Deparse->new;
889 local $Test::Builder::Level = $Test::Builder::Level + 1;
891 my ($got, $expect) = @_;
893 skip "Not testing equality of source containing defined-or operator on this perl $]", 1
894 if ( "$]" < 5.010 and $expect =~ m!\Q//=! );
896 $expect =~ s/__NBC__/perlstring($DBIx::Class::ResultSource::RowParser::Util::null_branch_class)/ge;
898 $expect = " { use strict; use warnings FATAL => 'uninitialized';\n$expect\n }";
900 my @normalized = map {
901 my $cref = eval "sub { $_ }" or do {
902 fail "Coderef does not compile!\n\n$@\n\n$_";
905 $deparser->coderef2text($cref);
908 &is (@normalized, $_[2]||() ) or do {
909 eval { require Test::Differences }
910 ? &Test::Differences::eq_or_diff( @normalized, $_[2]||() )
911 : note ("Original sources:\n\n$got\n\n$expect\n")