From: Peter Rabbitson Date: Tue, 5 Mar 2013 05:49:53 +0000 (+0100) Subject: Still do null-branch pruning when we are using our own inflate_result() X-Git-Tag: v0.08242~7 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class.git;a=commitdiff_plain;h=79adc44f8b50de05a1d31f9b3d4a64b137c7d0d8 Still do null-branch pruning when we are using our own inflate_result() 52864fbd was too aggressive in removing stuff - inheritance no longer matters, but which method we will be calling does. If we are still using our own inflate_result() there is no point of doing the double work of blessing and then skipping null branches. --- diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index cedb982..fd9d593 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -1368,12 +1368,23 @@ sub _construct_results { my $infmap = $attrs->{as}; - $self->{_result_inflator}{is_hri} = do { ( $inflator_cref == ( - require DBIx::Class::ResultClass::HashRefInflator - && - DBIx::Class::ResultClass::HashRefInflator->can('inflate_result') - ) ) ? 1 : 0 - } unless defined $self->{_result_inflator}{is_hri}; + + $self->{_result_inflator}{is_core_row} = ( ( + $inflator_cref + == + ( \&DBIx::Class::Row::inflate_result || die "No ::Row::inflate_result() - can't happen" ) + ) ? 1 : 0 ) unless defined $self->{_result_inflator}{is_core_row}; + + $self->{_result_inflator}{is_hri} = ( ( + ! $self->{_result_inflator}{is_core_row} + and + $inflator_cref == ( + require DBIx::Class::ResultClass::HashRefInflator + && + DBIx::Class::ResultClass::HashRefInflator->can('inflate_result') + ) + ) ? 1 : 0 ) unless defined $self->{_result_inflator}{is_hri}; + if (! $attrs->{_related_results_construction}) { # construct a much simpler array->hash folder for the one-table cases right here @@ -1401,7 +1412,7 @@ sub _construct_results { ); } } - # Special-case multi-object HRI (we always prune) + # Special-case multi-object HRI (we always prune, and there is no $inflator_cref pass) elsif ($self->{_result_inflator}{is_hri}) { ( $self->{_row_parser}{hri} ||= $rsrc->_mk_row_parser({ eval => 1, @@ -1410,17 +1421,20 @@ sub _construct_results { collapse => $attrs->{collapse}, premultiplied => $attrs->{_main_source_premultiplied}, hri_style => 1, + prune_null_branches => 1, }) )->($rows, @extra_collapser_args); } # Regular multi-object else { + my $parser_type = $self->{_result_inflator}{is_core_row} ? 'classic_pruning' : 'classic_nonpruning'; - ( $self->{_row_parser}{classic} ||= $rsrc->_mk_row_parser({ + ( $self->{_row_parser}{$parser_type} ||= $rsrc->_mk_row_parser({ eval => 1, inflate_map => $infmap, selection => $attrs->{select}, collapse => $attrs->{collapse}, premultiplied => $attrs->{_main_source_premultiplied}, + prune_null_branches => $self->{_result_inflator}{is_core_row}, }) )->($rows, @extra_collapser_args); $_ = $inflator_cref->($res_class, $rsrc, @$_) for @$rows; diff --git a/lib/DBIx/Class/ResultSource/RowParser.pm b/lib/DBIx/Class/ResultSource/RowParser.pm index 695736e..e3f6358 100644 --- a/lib/DBIx/Class/ResultSource/RowParser.pm +++ b/lib/DBIx/Class/ResultSource/RowParser.pm @@ -95,42 +95,41 @@ sub _resolve_prefetch { sub _mk_row_parser { my ($self, $args) = @_; - my $val_index = { map - { $args->{inflate_map}[$_] => $_ } - ( 0 .. $#{$args->{inflate_map}} ) - }; - - my $src; - - if (! $args->{collapse} ) { - $src = assemble_simple_parser({ - val_index => $val_index, - hri_style => $args->{hri_style}, - }); - } - else { - my $collapse_map = $self->_resolve_collapse ({ - premultiplied => $args->{premultiplied}, - # FIXME - # only consider real columns (not functions) during collapse resolution - # this check shouldn't really be here, as fucktards are not supposed to - # alias random crap to existing column names anyway, but still - just in - # case - # FIXME !!!! - this does not yet deal with unbalanced selectors correctly - # (it is now trivial as the attrs specify where things go out of sync - # needs MOAR tests) - as => { map - { ref $args->{selection}[$val_index->{$_}] ? () : ( $_ => $val_index->{$_} ) } - keys %$val_index - } - }); - - $src = assemble_collapsing_parser({ - val_index => $val_index, - collapse_map => $collapse_map, - hri_style => $args->{hri_style}, - }); - } + die "HRI without pruning makes zero sense" + if ( $args->{hri_style} && ! $args->{prune_null_branches} ); + + my %common = ( + hri_style => $args->{hri_style}, + prune_null_branches => $args->{prune_null_branches}, + val_index => { map + { $args->{inflate_map}[$_] => $_ } + ( 0 .. $#{$args->{inflate_map}} ) + }, + ); + + my $src = $args->{collapse} + ? assemble_collapsing_parser({ + %common, + collapse_map => $self->_resolve_collapse ({ + # FIXME + # only consider real columns (not functions) during collapse resolution + # this check shouldn't really be here, as fucktards are not supposed to + # alias random crap to existing column names anyway, but still - just in + # case + # FIXME !!!! - this does not yet deal with unbalanced selectors correctly + # (it is now trivial as the attrs specify where things go out of sync + # needs MOAR tests) + as => { map + { ref $args->{selection}[$common{val_index}{$_}] ? () : ( $_ => $common{val_index}{$_} ) } + keys %{$common{val_index}} + }, + premultiplied => $args->{premultiplied}, + }) + }) + : assemble_simple_parser( + \%common + ) + ; return $args->{eval} ? ( eval "sub $src" || die $@ ) diff --git a/lib/DBIx/Class/ResultSource/RowParser/Util.pm b/lib/DBIx/Class/ResultSource/RowParser/Util.pm index c69dfa3..f80fd7d 100644 --- a/lib/DBIx/Class/ResultSource/RowParser/Util.pm +++ b/lib/DBIx/Class/ResultSource/RowParser/Util.pm @@ -65,7 +65,7 @@ sub __visit_infmap_simple { sort { $a <=> $b } values %{$rel_cols->{$rel}} ; - if ($args->{hri_style}) { + if ($args->{prune_null_branches}) { $rel_struct = sprintf ( '( (%s) ? undef : %s )', $branch_null_checks, $rel_struct, @@ -109,7 +109,7 @@ sub assemble_collapsing_parser { my $args = shift; # it may get unset further down - my $no_rowid_container = $args->{hri_style}; + my $no_rowid_container = $args->{prune_null_branches}; my ($top_node_key, $top_node_key_assembler); @@ -306,14 +306,15 @@ sub __visit_infmap_collapse { ) ) { - if ($args->{hri_style}) { + if ($args->{prune_null_branches}) { # start of wrap of the entire chain in a conditional - splice @src, $rel_src_pos, 0, sprintf "( ! defined %s )\n ? %s{%s} = %s\n : do {", + splice @src, $rel_src_pos, 0, sprintf "( ! defined %s )\n ? %s%s{%s} = %s\n : do {", "'\xFF__VALPOS__${first_distinct_child_idcol}__\xFF'", $node_idx_slot, + $args->{hri_style} ? '' : '[1]', perlstring($rel), - $relinfo->{-is_single} ? 'undef' : '[]' + ($args->{hri_style} && $relinfo->{-is_single}) ? 'undef' : '[]' ; # end of wrap diff --git a/t/resultset/inflate_result_api.t b/t/resultset/inflate_result_api.t index 85ec3e1..1fa917a 100644 --- a/t/resultset/inflate_result_api.t +++ b/t/resultset/inflate_result_api.t @@ -1,5 +1,6 @@ use strict; use warnings; +no warnings 'exiting'; use Test::More; use Test::Deep; @@ -45,416 +46,460 @@ $schema->resultset('CD')->create({ $schema->resultset('CD')->create({ artist => 1, year => 1977, title => "fuzzy_1" }); -{ - package DBICTest::_IRCapture; - sub inflate_result { [@_[2,3]] }; -} +$schema->resultset('Artist')->create({ name => "${_}_cdless" }) + for (qw( Z A )); -cmp_structures( - ([$schema->resultset ('CD')->search ({}, { - result_class => 'DBICTest::_IRCapture', - prefetch => { single_track => { cd => 'artist' } }, - order_by => 'me.cdid', - })->all]), - [ - [ - { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, - { single_track => bless( [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - { cd => bless ( [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { - artist => bless ( [ - { artistid => undef, name => undef, charfield => undef, rank => undef } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) - } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } - ], - [ - { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, - { single_track => bless( [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - { cd => bless ( [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { - artist => bless ( [ - { artistid => undef, name => undef, charfield => undef, rank => undef } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) - } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } - ], +# subs at the end of the test refer to this +my $native_inflator; + +### TESTS START +# run entire test twice - with and without "native inflator" +INFTYPE: for ('', '(native inflator)') { + + $native_inflator = $_; + + cmp_structures( + rs_contents( $schema->resultset ('CD')->search_rs ({}, { + prefetch => { single_track => { cd => 'artist' } }, + order_by => 'me.cdid', + }) ), [ - { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, - { single_track => [ - { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef }, - { cd => [ - { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, - { - artist => [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 } - ] - } + [ + { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, + { single_track => code(sub { null_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + { cd => code(sub { null_branch ( \@_, [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { + artist => code(sub { null_branch ( \@_, [ + { artistid => undef, name => undef, charfield => undef, rank => undef } + ] ) } ) + } + ] ) } ) } + ] ) } ) } + ], + [ + { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, + { single_track => code(sub { null_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + { cd => code(sub { null_branch ( \@_, [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { + artist => code(sub { null_branch ( \@_, [ + { artistid => undef, name => undef, charfield => undef, rank => undef } + ] ) } ) + } + ] ) } ) } + ] ) } ) } + ], + [ + { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, + { single_track => [ + { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef }, + { cd => [ + { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, + { + artist => [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 } + ] + } + ] } ] } - ] } - ], - [ - { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, - { single_track => bless( [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - { cd => bless ( [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { - artist => bless ( [ - { artistid => undef, name => undef, charfield => undef, rank => undef } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) - } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } + ], + [ + { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, + { single_track => code(sub { null_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + { cd => code(sub { null_branch ( \@_, [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { + artist => code(sub { null_branch ( \@_, [ + { artistid => undef, name => undef, charfield => undef, rank => undef } + ] ) } ) + } + ] ) } ) } + ] ) } ) } + ], ], - ], - 'Simple 1:1 descend with classic prefetch' -); + "Simple 1:1 descend with classic prefetch $native_inflator" + ); -cmp_structures( - [$schema->resultset ('CD')->search ({}, { - result_class => 'DBICTest::_IRCapture', - join => { single_track => { cd => 'artist' } }, - columns => [ - { 'year' => 'me.year' }, - { 'genreid' => 'me.genreid' }, - { 'single_track.cd.artist.artistid' => 'artist.artistid' }, - { 'title' => 'me.title' }, - { 'artist' => 'me.artist' }, - ], - order_by => 'me.cdid', - })->all], - [ + cmp_structures( + rs_contents( $schema->resultset ('CD')->search_rs ({}, { + join => { single_track => { cd => 'artist' } }, + columns => [ + { 'year' => 'me.year' }, + { 'genreid' => 'me.genreid' }, + { 'single_track.cd.artist.artistid' => 'artist.artistid' }, + { 'title' => 'me.title' }, + { 'artist' => 'me.artist' }, + ], + order_by => 'me.cdid', + }) ), [ - { artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, - { single_track => bless( [ - undef, - { cd => [ + [ + { artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, + { single_track => code(sub { null_branch ( \@_, [ undef, - { - artist => [ - { artistid => undef } - ] - } - ] } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } - ], - [ - { artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, - { single_track => bless( [ - undef, - { cd => [ + { cd => [ + undef, + { + artist => [ + { artistid => undef } + ] + } + ] } + ] ) } ) } + ], + [ + { artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, + { single_track => code(sub { null_branch ( \@_, [ undef, - { - artist => [ - { artistid => undef } - ] - } - ] } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } - ], - [ - { artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, - { single_track => [ - undef, - { cd => [ + { cd => [ + undef, + { + artist => [ + { artistid => undef } + ] + } + ] } + ] ) } ) } + ], + [ + { artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, + { single_track => [ undef, - { - artist => [ - { artistid => 1 } - ] - } + { cd => [ + undef, + { + artist => [ + { artistid => 1 } + ] + } + ] } ] } - ] } - ], - [ - { artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, - { single_track => bless( [ - undef, - { cd => [ + ], + [ + { artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, + { single_track => code(sub { null_branch ( \@_, [ undef, - { - artist => [ - { artistid => undef } - ] - } - ] } - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) } + { cd => [ + undef, + { + artist => [ + { artistid => undef } + ] + } + ] } + ] ) } ) } + ], ], - ], - 'Simple 1:1 descend with missing selectors' -); + "Simple 1:1 descend with missing selectors $native_inflator", + ); -cmp_structures( - ([$schema->resultset ('CD')->search ({}, { - result_class => 'DBICTest::_IRCapture', - prefetch => [ { single_track => { cd => { artist => { cds => 'tracks' } } } } ], - order_by => [qw/me.cdid tracks.trackid/], - })->all]), - [ + cmp_structures( + rs_contents( $schema->resultset ('CD')->search_rs ({}, { + prefetch => [ { single_track => { cd => { artist => { cds => 'tracks' } } } } ], + order_by => [qw/me.cdid tracks.trackid/], + }) ), [ - { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, - { single_track => bless( [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - { cd => [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { - artist => [ - { artistid => undef, name => undef, charfield => undef, rank => undef }, - { cds => bless( [ [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { tracks => bless( [ [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - ] ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ] ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ], - }, - ] }, - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ], - [ - { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, - { single_track => bless( [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - { cd => [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { - artist => [ - { artistid => undef, name => undef, charfield => undef, rank => undef }, - { cds => bless( [ [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { tracks => bless( [ [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - ] ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ] ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ], - }, - ] }, - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ], - [ - { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, - { single_track => [ - { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef }, - { cd => [ - { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, - { - artist => [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - [ - { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, - { tracks => bless( [ - [ { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef } ], - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ], - [ - { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, - { tracks => [ - [ { trackid => 1, title => 'm1', position => 1, cd => 1, last_updated_at => undef, last_updated_on => undef } ], - [ { trackid => 2, title => 'm2', position => 2, cd => 1, last_updated_at => undef, last_updated_on => undef } ], - [ { trackid => 3, title => 'm3', position => 3, cd => 1, last_updated_at => undef, last_updated_on => undef } ], - [ { trackid => 4, title => 'm4', position => 4, cd => 1, last_updated_at => undef, last_updated_on => undef } ], - ]}, - ], - [ - { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, - { tracks => [ - [ { trackid => 5, title => 'o2', position => 2, cd => 2, last_updated_at => undef, last_updated_on => undef } ], - [ { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef } ], - ]}, - ], - [ - { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, - { tracks => [ - [ { trackid => 7, title => 'e1', position => 1, cd => 3, last_updated_at => undef, last_updated_on => undef } ], - [ { trackid => 8, title => 'e2', position => 2, cd => 3, last_updated_at => undef, last_updated_on => undef } ], - [ { trackid => 9, title => 'e3', position => 3, cd => 3, last_updated_at => undef, last_updated_on => undef } ], - ]}, - ], - ]}, - ] - } + [ + { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, + { single_track => code(sub { null_collapsed_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + { cd => [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { + artist => [ + { artistid => undef, name => undef, charfield => undef, rank => undef }, + { cds => code(sub { null_collapsed_branch ( \@_, [ [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { tracks => code(sub { null_collapsed_branch ( \@_, [ [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + ] ] ) } ) }, + ] ] ) } ) }, + ], + }, + ] }, + ] ) } ) }, + ], + [ + { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, + { single_track => code(sub { null_collapsed_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + { cd => [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { + artist => [ + { artistid => undef, name => undef, charfield => undef, rank => undef }, + { cds => code(sub { null_collapsed_branch ( \@_, [ [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { tracks => code(sub { null_collapsed_branch ( \@_, [ [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + ] ] ) } ) }, + ] ] ) } ) }, + ], + }, + ] }, + ] ) } ) }, + ], + [ + { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, + { single_track => [ + { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef }, + { cd => [ + { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, + { + artist => [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + [ + { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, + { tracks => code(sub { null_collapsed_branch ( \@_, [ + [ { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef } ], + ] ) } ) }, + ], + [ + { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, + { tracks => [ + [ { trackid => 1, title => 'm1', position => 1, cd => 1, last_updated_at => undef, last_updated_on => undef } ], + [ { trackid => 2, title => 'm2', position => 2, cd => 1, last_updated_at => undef, last_updated_on => undef } ], + [ { trackid => 3, title => 'm3', position => 3, cd => 1, last_updated_at => undef, last_updated_on => undef } ], + [ { trackid => 4, title => 'm4', position => 4, cd => 1, last_updated_at => undef, last_updated_on => undef } ], + ]}, + ], + [ + { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, + { tracks => [ + [ { trackid => 5, title => 'o2', position => 2, cd => 2, last_updated_at => undef, last_updated_on => undef } ], + [ { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef } ], + ]}, + ], + [ + { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, + { tracks => [ + [ { trackid => 7, title => 'e1', position => 1, cd => 3, last_updated_at => undef, last_updated_on => undef } ], + [ { trackid => 8, title => 'e2', position => 2, cd => 3, last_updated_at => undef, last_updated_on => undef } ], + [ { trackid => 9, title => 'e3', position => 3, cd => 3, last_updated_at => undef, last_updated_on => undef } ], + ]}, + ], + ]}, + ] + } + ] } ] } - ] } - ], - [ - { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, - { single_track => bless( [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - { cd => [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { - artist => [ - { artistid => undef, name => undef, charfield => undef, rank => undef }, - { cds => bless( [ [ - { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, - { tracks => bless( [ [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - ] ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ] ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ], - }, - ] }, - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, + ], + [ + { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, + { single_track => code(sub { null_collapsed_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + { cd => [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { + artist => [ + { artistid => undef, name => undef, charfield => undef, rank => undef }, + { cds => code(sub { null_collapsed_branch ( \@_, [ [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { tracks => code(sub { null_collapsed_branch ( \@_, [ [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + ] ] ) } ) }, + ] ] ) } ) }, + ], + }, + ] }, + ] ) } ) }, + ], ], - ], - 'Collapsing 1:1 ending in chained has_many with classic prefetch' -); + "Collapsing 1:1 ending in chained has_many with classic prefetch $native_inflator", + ); -cmp_structures ( - ([$schema->resultset ('Artist')->search ({}, { - result_class => 'DBICTest::_IRCapture', - join => { cds => 'tracks' }, - '+columns' => [ - (map { "cds.$_" } $schema->source('CD')->columns), - (map { +{ "cds.tracks.$_" => "tracks.$_" } } $schema->source('Track')->columns), - ], - order_by => [qw/cds.cdid tracks.trackid/], - })->all]), - [ + cmp_structures ( + rs_contents( $schema->resultset ('Artist')->search_rs ({}, { + join => { cds => 'tracks' }, + '+columns' => [ + (map { "cds.$_" } $schema->source('CD')->columns), + (map { +{ "cds.tracks.$_" => "tracks.$_" } } $schema->source('Track')->columns), + ], + order_by => [qw/cds.cdid tracks.trackid me.name/], + }) ), [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, - { tracks => [ - { trackid => 1, title => 'm1', position => 1, cd => 1, last_updated_at => undef, last_updated_on => undef }, + [ + { artistid => 3, name => 'A_cdless', charfield => undef, rank => 13 }, + { cds => code(sub { null_branch ( \@_, [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { tracks => code(sub { null_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + ] ) } ) }, + ] ) } ) }, + ], + [ + { artistid => 2, name => 'Z_cdless', charfield => undef, rank => 13 }, + { cds => code(sub { null_branch ( \@_, [ + { cdid => undef, single_track => undef, artist => undef, genreid => undef, year => undef, title => undef }, + { tracks => code(sub { null_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + ] ) } ) }, + ] ) } ) }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, + { tracks => [ + { trackid => 1, title => 'm1', position => 1, cd => 1, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, - ], - [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, - { tracks => [ - { trackid => 2, title => 'm2', position => 2, cd => 1, last_updated_at => undef, last_updated_on => undef }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, + { tracks => [ + { trackid => 2, title => 'm2', position => 2, cd => 1, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, - ], - [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, - { tracks => [ - { trackid => 3, title => 'm3', position => 3, cd => 1, last_updated_at => undef, last_updated_on => undef }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, + { tracks => [ + { trackid => 3, title => 'm3', position => 3, cd => 1, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, - ], - [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, - { tracks => [ - { trackid => 4, title => 'm4', position => 4, cd => 1, last_updated_at => undef, last_updated_on => undef }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 1, single_track => undef, artist => 1, genreid => 1, year => 1981, title => "Magnetic Fields" }, + { tracks => [ + { trackid => 4, title => 'm4', position => 4, cd => 1, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, - ], - [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, - { tracks => [ - { trackid => 5, title => 'o2', position => 2, cd => 2, last_updated_at => undef, last_updated_on => undef }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, + { tracks => [ + { trackid => 5, title => 'o2', position => 2, cd => 2, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, - ], - [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, - { tracks => [ - { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 2, single_track => undef, artist => 1, genreid => undef, year => 1976, title => "Oxygene" }, + { tracks => [ + { trackid => 6, title => 'o1', position => 1, cd => 2, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, - ], - [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, - { tracks => [ - { trackid => 7, title => 'e1', position => 1, cd => 3, last_updated_at => undef, last_updated_on => undef }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, + { tracks => [ + { trackid => 7, title => 'e1', position => 1, cd => 3, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, - ], - [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, - { tracks => [ - { trackid => 8, title => 'e2', position => 2, cd => 3, last_updated_at => undef, last_updated_on => undef }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, + { tracks => [ + { trackid => 8, title => 'e2', position => 2, cd => 3, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, - ], - [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, - { tracks => [ - { trackid => 9, title => 'e3', position => 3, cd => 3, last_updated_at => undef, last_updated_on => undef }, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 3, single_track => 6, artist => 1, genreid => 1, year => 1978, title => "Equinoxe" }, + { tracks => [ + { trackid => 9, title => 'e3', position => 3, cd => 3, last_updated_at => undef, last_updated_on => undef }, + ]}, ]}, - ]}, + ], + [ + { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, + { cds => [ + { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, + { tracks => code(sub { null_branch ( \@_, [ + { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, + ] ) } ) }, + ]}, + ], ], + "Non-Collapsing chained has_many $native_inflator", + ); + + cmp_structures ( + rs_contents( $schema->resultset ('Artist')->search_rs ({}, { + collapse => 1, + join => 'cds', + columns => [qw( cds.title cds.artist )], + order_by => [qw( me.name cds.title )], + }) ), [ - { artistid => 1, name => 'JMJ', charfield => undef, rank => 13 }, - { cds => [ - { cdid => 4, single_track => undef, artist => 1, genreid => undef, year => 1977, title => "fuzzy_1" }, - { tracks => bless( [ - { trackid => undef, title => undef, position => undef, cd => undef, last_updated_at => undef, last_updated_on => undef }, - ], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ) }, - ]}, + [ + undef, + { cds => code(sub { null_collapsed_branch ( \@_, [ + [ { artist => undef, title => undef } ] + ] ) } ) }, + ], + [ + undef, + { cds => [ + [ { artist => 1, title => "Equinoxe" } ], + [ { artist => 1, title => "Magnetic Fields" } ], + [ { artist => 1, title => "Oxygene" } ], + [ { artist => 1, title => "fuzzy_1" } ], + ] } + ], + [ + undef, + { cds => code(sub { null_collapsed_branch ( \@_, [ + [ { artist => undef, title => undef } ] + ] ) } ) }, + ], ], - ], - 'Non-Collapsing chained has_many' -); + "Expected output of collapsing 1:M with empty root selection $native_inflator", + ); +} -$schema->resultset('Artist')->create({ name => "${_}_cdless" }) - for (qw( Z A )); +sub null_branch { + cmp_deeply( + $_[0][0], + $native_inflator ? undef : bless( $_[1], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ), + ); +} +sub null_collapsed_branch { + cmp_deeply( + $_[0][0], + $native_inflator ? [] : bless( $_[1], $DBIx::Class::ResultSource::RowParser::Util::null_branch_class ), + ); +} -cmp_structures ( - [$schema->resultset ('Artist')->search ({}, { - result_class => 'DBICTest::_IRCapture', - collapse => 1, - join => 'cds', - columns => [qw( cds.title cds.artist )], - order_by => [qw( me.name cds.title )], - })->all], - [ - [ - undef, - { cds => bless( [ - [ { artist => undef, title => undef } ] - ], 'DBIx::ResultParser::RelatedNullBranch' ) }, - ], - [ - undef, - { cds => [ - [ { artist => 1, title => "Equinoxe" } ], - [ { artist => 1, title => "Magnetic Fields" } ], - [ { artist => 1, title => "Oxygene" } ], - [ { artist => 1, title => "fuzzy_1" } ], - ] } - ], - [ - undef, - { cds => bless( [ - [ { artist => undef, title => undef } ] - ], 'DBIx::ResultParser::RelatedNullBranch' ) }, - ], - ], - 'Expected output of collapsing 1:M with empty root selection', -); +{ + package DBICTest::_IRCapture; + sub inflate_result { [@_[2,3]] }; +} + +sub rs_contents { + my $rs = shift; + $rs->result_class('DBICTest::_IRCapture'); + die 'eeeeek - preprocessed $rs' if defined $rs->{_result_inflator}{is_core_row}; + $rs->{_result_inflator}{is_core_row} = 1 if $native_inflator; + [$rs->all], +} sub cmp_structures { my ($left, $right, $msg) = @_; local $Test::Builder::Level = $Test::Builder::Level + 1; - cmp_deeply($left, $right, $msg||()); + cmp_deeply($left, $right, $msg||()) or next INFTYPE; } done_testing; diff --git a/t/resultset/rowparser_internals.t b/t/resultset/rowparser_internals.t index 97ba69a..848b3a7 100644 --- a/t/resultset/rowparser_internals.t +++ b/t/resultset/rowparser_internals.t @@ -138,7 +138,44 @@ is_same_src ( is_same_src ( $schema->source ('CD')->_mk_row_parser({ + prune_null_branches => 1, + inflate_map => $infmap, + }), + '$_ = [ + { artist => $_->[5], title => $_->[4], year => $_->[2] }, + { + single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) ) ? undef : [ + undef, + { + cd => [ + undef, + { + artist => [ + { artistid => $_->[1] }, + { + cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) ? undef : [ + { cdid => $_->[3] }, + { + tracks => ( ! defined $_->[0] ) ? undef : [ + { title => $_->[0] }, + ] + } + ] + } + ] + } + ] + } + ] + } + ] for @{$_[0]}', + '1:1 descending non-collapsing pruning parser terminating with chained 1:M:M', +); + +is_same_src ( + $schema->source ('CD')->_mk_row_parser({ hri_style => 1, + prune_null_branches => 1, inflate_map => $infmap, }), '$_ = { @@ -268,6 +305,7 @@ is_same_src ( inflate_map => $infmap, collapse => 1, hri_style => 1, + prune_null_branches => 1, }), ' my $rows_pos = 0; my ($result_pos, @collapse_idx, $cur_row_data); @@ -451,9 +489,10 @@ is_same_src ( $schema->source ('CD')->_mk_row_parser({ inflate_map => $infmap, collapse => 1, + prune_null_branches => 1, }), ' my $rows_pos = 0; - my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids); + my ($result_pos, @collapse_idx, $cur_row_data); while ($cur_row_data = ( ( $rows_pos >= 0 and $_[0][$rows_pos++] ) @@ -461,56 +500,56 @@ is_same_src ( ( $_[1] and $rows_pos = -1 and $_[1]->() ) ) ) { - $cur_row_ids{0} = defined $cur_row_data->[0] ? $cur_row_data->[0] : "\0NULL\xFF$rows_pos\xFF0\0"; - $cur_row_ids{1} = defined $cur_row_data->[1] ? $cur_row_data->[1] : "\0NULL\xFF$rows_pos\xFF1\0"; - $cur_row_ids{5} = defined $cur_row_data->[5] ? $cur_row_data->[5] : "\0NULL\xFF$rows_pos\xFF5\0"; - $cur_row_ids{6} = defined $cur_row_data->[6] ? $cur_row_data->[6] : "\0NULL\xFF$rows_pos\xFF6\0"; - $cur_row_ids{8} = defined $cur_row_data->[8] ? $cur_row_data->[8] : "\0NULL\xFF$rows_pos\xFF8\0"; - $cur_row_ids{10} = defined $cur_row_data->[10] ? $cur_row_data->[10] : "\0NULL\xFF$rows_pos\xFF10\0"; - # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] - $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last; + $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_data->[1]} and (unshift @{$_[2]}, $cur_row_data) and last; - $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] }]; + $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] }]; - $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} ||= $collapse_idx[1]{$cur_row_ids{1}} = []; - $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}} = []; - $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }]; + $collapse_idx[0]{$cur_row_data->[1]}[1]{existing_single_track} ||= $collapse_idx[1]{$cur_row_data->[1]} = []; + $collapse_idx[1]{$cur_row_data->[1]}[1]{cd} ||= $collapse_idx[2]{$cur_row_data->[1]} = []; + $collapse_idx[2]{$cur_row_data->[1]}[1]{artist} ||= $collapse_idx[3]{$cur_row_data->[1]} = [{ artistid => $cur_row_data->[1] }]; - (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} ) - and - push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, ( - $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] }] - ); - defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ ); + (! defined($cur_row_data->[6])) ? $collapse_idx[3]{$cur_row_data->[1]}[1]{cds} = [] : do { + (! $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]} ) + and + push @{ $collapse_idx[3]{$cur_row_data->[1]}[1]{cds} }, ( + $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] }] + ); - (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} ) - and - push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, ( - $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }] - ); - defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ ); + (! defined($cur_row_data->[8]) ) ? $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]}[1]{tracks} = [] : do { - (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} ) - and - push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, ( - $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }] - ); - defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ ); + (! $collapse_idx[5]{$cur_row_data->[1]}{$cur_row_data->[6]}{$cur_row_data->[8]} ) + and + push @{ $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]}[1]{tracks} }, ( + $collapse_idx[5]{$cur_row_data->[1]}{$cur_row_data->[6]}{$cur_row_data->[8]} = [{ title => $cur_row_data->[8] }] + ); + }; + }; - $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}} = []; - defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ ); + (! defined($cur_row_data->[5]) ) ? $collapse_idx[0]{$cur_row_data->[1]}[1]{tracks} = [] : do { - (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} ) - and - push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, ( - $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] }] - ); + (! $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]} ) + and + push @{ $collapse_idx[0]{$cur_row_data->[1]}[1]{tracks} }, ( + $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]} = [{ title => $cur_row_data->[5] }] + ); + + (! defined($cur_row_data->[10]) ) ? $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]}[1]{lyrics} = [] : do { + + $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]} = []; + + (! $collapse_idx[8]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]} ) + and + push @{ $collapse_idx[7]{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]}[1]{existing_lyric_versions} }, ( + $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] }] + ); + }; + }; } $#{$_[0]} = $result_pos - 1; ', - 'Multiple has_many on multiple branches with branch torture test', + 'Multiple has_many on multiple branches with branch pruning torture test', ); $infmap = [ @@ -634,6 +673,7 @@ is_same_src ( inflate_map => $infmap, collapse => 1, hri_style => 1, + prune_null_branches => 1, }), ' my $rows_pos = 0; my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);