Still do null-branch pruning when we are using our own inflate_result()
Peter Rabbitson [Tue, 5 Mar 2013 05:49:53 +0000 (06:49 +0100)]
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.

lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/ResultSource/RowParser.pm
lib/DBIx/Class/ResultSource/RowParser/Util.pm
t/resultset/inflate_result_api.t
t/resultset/rowparser_internals.t

index cedb982..fd9d593 100644 (file)
@@ -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;
index 695736e..e3f6358 100644 (file)
@@ -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 $@ )
index c69dfa3..f80fd7d 100644 (file)
@@ -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
index 85ec3e1..1fa917a 100644 (file)
@@ -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;
index 97ba69a..848b3a7 100644 (file)
@@ -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);