From: Peter Rabbitson Date: Sun, 27 Jul 2014 21:50:25 +0000 (+0200) Subject: Tighten even more inflate_result() invocations, for crazy overloads X-Git-Tag: v0.082800~103 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=30681c23187d5f13d57eda0c97dda1be5fb291d1;p=dbsrgits%2FDBIx-Class.git Tighten even more inflate_result() invocations, for crazy overloads --- diff --git a/Changes b/Changes index 2aebd6d..7f174c4 100644 --- a/Changes +++ b/Changes @@ -22,6 +22,8 @@ Revision history for DBIx::Class existed between storage accessor setters and the determine_driver routines, triggering a connection before the set-cycle is finished - Fix collapse being ignored on single-origin selection (RT#95658) + - Fix incorrect behavior on custom result_class inflators altering + the amount of returned results - Fix failure to detect stable order criteria when in iterator mode of a has_many prefetch off a search_related chain - Prevent erroneous database hit when accessing prefetched related diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 44adfe8..8745c5f 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -1429,15 +1429,19 @@ sub _construct_results { # # crude unscientific benchmarking indicated the shortcut eval is not worth it for # this particular resultset size - elsif (@$rows < 60) { + elsif ( $self->{_result_inflator}{is_core_row} and @$rows < 60 ) { for my $r (@$rows) { $r = $inflator_cref->($res_class, $rsrc, { map { $infmap->[$_] => $r->[$_] } (0..$#$infmap) } ); } } else { eval sprintf ( - '$_ = $inflator_cref->($res_class, $rsrc, { %s }) for @$rows', - join (', ', map { "\$infmap->[$_] => \$_->[$_]" } 0..$#$infmap ) + ( $self->{_result_inflator}{is_core_row} + ? '$_ = $inflator_cref->($res_class, $rsrc, { %s }) for @$rows' + # a custom inflator may be a multiplier/reductor - put it in direct list ctx + : '@$rows = map { $inflator_cref->($res_class, $rsrc, { %s } ) } @$rows' + ), + ( join (', ', map { "\$infmap->[$_] => \$_->[$_]" } 0..$#$infmap ) ) ); } } @@ -1510,10 +1514,15 @@ EOS $next_cref ? ( $next_cref, $self->{_stashed_rows} = [] ) : (), ); - # Special-case multi-object HRI - there is no $inflator_cref pass - unless ($self->{_result_inflator}{is_hri}) { + # simple in-place substitution, does not regrow $rows + if ($self->{_result_inflator}{is_core_row}) { $_ = $inflator_cref->($res_class, $rsrc, @$_) for @$rows } + # Special-case multi-object HRI - there is no $inflator_cref pass at all + elsif ( ! $self->{_result_inflator}{is_hri} ) { + # the inflator may be a multiplier/reductor - put it in list ctx + @$rows = map { $inflator_cref->($res_class, $rsrc, @$_) } @$rows; + } } # The @$rows check seems odd at first - why wouldn't we want to warn diff --git a/t/resultset/inflate_result_api.t b/t/resultset/inflate_result_api.t index 1fa917a..e6bedc2 100644 --- a/t/resultset/inflate_result_api.t +++ b/t/resultset/inflate_result_api.t @@ -502,4 +502,31 @@ sub cmp_structures { cmp_deeply($left, $right, $msg||()) or next INFTYPE; } +{ + package DBICTest::_DoubleResult; + + sub inflate_result { + my $class = shift; + return map { DBIx::Class::ResultClass::HashRefInflator->inflate_result(@_) } (1,2); + } +} + +my $oxygene_rs = $schema->resultset('CD')->search({ 'me.title' => 'Oxygene' }); + +is_deeply( + [ $oxygene_rs->search({}, { result_class => 'DBICTest::_DoubleResult' })->all ], + [ ({ $oxygene_rs->single->get_columns }) x 2 ], +); + +is_deeply( + [ $oxygene_rs->search({}, { + result_class => 'DBICTest::_DoubleResult', prefetch => [qw(artist tracks)], + order_by => [qw(me.cdid tracks.title)], + })->all ], + [ (@{$oxygene_rs->search({}, { + prefetch=> [qw(artist tracks)], + order_by => [qw(me.cdid tracks.title)], + })->all_hri}) x 2 ], +); + done_testing;