From: Dagfinn Ilmari Mannsåker Date: Fri, 28 Mar 2014 16:48:17 +0000 (+0000) Subject: Populate caches for related result sets even if they're empty X-Git-Tag: v0.082800~166 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class.git;a=commitdiff_plain;h=b6b8f72fff65a26976069f55cf134e6e607e6112 Populate caches for related result sets even if they're empty This avoids unnecessary database hits when accessing prefetched related resultsets with no rows. --- diff --git a/Changes b/Changes index 06e9cf0..57e6135 100644 --- a/Changes +++ b/Changes @@ -19,6 +19,8 @@ Revision history for DBIx::Class - Fix on_connect_* not always firing in some cases - a race condition existed between storage accessor setters and the determine_driver routines, triggering a connection before the set-cycle is finished + - Prevent erroneous database hit when accessing prefetched related + resultsets with no rows - Fix incorrect handling of custom relationship conditions returning SQLA literal expressions - Fix multi-value literal populate not working with simplified bind diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 92665d6..2bc320b 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -3098,11 +3098,11 @@ sub related_resultset { if (my $cache = $self->get_cache) { my @related_cache = map - { @{$_->related_resultset($rel)->get_cache||[]} } + { $_->related_resultset($rel)->get_cache || () } @$cache ; - $new->set_cache(\@related_cache) if @related_cache; + $new->set_cache([ map @$_, @related_cache ]) if @related_cache == @$cache; } $new; diff --git a/t/prefetch/empty_cache.t b/t/prefetch/empty_cache.t new file mode 100644 index 0000000..6fa4bb9 --- /dev/null +++ b/t/prefetch/empty_cache.t @@ -0,0 +1,39 @@ +use strict; +use warnings; + +use Test::More; + +use lib qw(t/lib); +use DBICTest; + +my $schema = DBICTest->init_schema(); + +my $no_albums_artist = { name => 'We Have No Albums' }; +$schema->resultset('Artist')->create($no_albums_artist); + +foreach ( + [empty => \'0 = 1', 0], + [nonempty => $no_albums_artist, 1], +) { + my ($desc, $cond, $count) = @$_; + + my $artists_rs = $schema->resultset('Artist') + ->search($cond, { prefetch => 'cds', cache => 1 }); + + $schema->is_executed_querycount( sub { + my @artists = $artists_rs->all; + is( 0+@{$artists_rs->get_cache}, $count, "$desc cache on original resultset" ); + is( 0+@artists, $count, "$desc original resultset" ); + }, 1, "->all on $desc original resultset hit db" ); + + $schema->is_executed_querycount( sub { + my $cds_rs = $artists_rs->related_resultset('cds'); + is_deeply( $cds_rs->get_cache, [], 'empty cache on related resultset' ); + + my @cds = $cds_rs->all; + is( 0+@cds, 0, 'empty related resultset' ); + }, 0, '->all on empty related resultest didn\'t hit db' ); +} + + +done_testing;