From: Daniel Ruoso Date: Mon, 22 Nov 2010 15:12:17 +0000 (-0300) Subject: support for prefetch from resultsource using extended_rels X-Git-Tag: v0.08190~1^2~14 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=3fc16c9aedbb4d864b98fbe9ed8c5cfe540f1496;p=dbsrgits%2FDBIx-Class.git support for prefetch from resultsource using extended_rels --- diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index 4f41baa..780aaa9 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -1675,7 +1675,7 @@ sub _resolve_prefetch { if ($rel_info->{attrs}{accessor} && $rel_info->{attrs}{accessor} eq 'multi') { $self->throw_exception( "Can't prefetch has_many ${pre} (join cond too complex)") - unless ref($rel_info->{cond}) eq 'HASH'; + unless (ref($rel_info->{cond}) eq 'HASH' || ref($rel_info->{cond}) eq 'CODE'); my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}" if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots } @@ -1697,9 +1697,17 @@ sub _resolve_prefetch { $collapse->{".${as_prefix}${pre}"} = [ $rel_source->_pri_cols ]; # action at a distance. prepending the '.' allows simpler code # in ResultSet->_collapse_result - my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); } - keys %{$rel_info->{cond}}; - push @$order, map { "${as}.$_" } @key; + + if (ref $rel_info->{cond} eq 'HASH') { + my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); } + keys %{$rel_info->{cond}}; + push @$order, map { "${as}.$_" } @key; + } else { # ref $rel_info->{cond} eq 'CODE' + # call the cond to get the keys... + my $cond_data = $rel_info->{cond}->({ foreign_alias => $as, + self_alias => $alias }); + push @$order, keys %$cond_data; + } if (my $rel_order = $rel_info->{attrs}{order_by}) { # this is kludgy and incomplete, I am well aware diff --git a/t/relationship/custom.t b/t/relationship/custom.t index 3b58926..369aeb0 100644 --- a/t/relationship/custom.t +++ b/t/relationship/custom.t @@ -32,13 +32,16 @@ map { ok($_->year < 2000 && $_->year > 1989) } @cds_90s; # the join must be a prefetch, but it can't work until the collapse rewrite is finished # (right-side vs left-side order) ##### -TODO: { - local $TODO = "Replace the join below with this when we fix the collapser"; - lives_ok { - my @all_artists_with_80_cds = $schema->resultset("Artist")->search - ({ 'cds_80s.cdid' => { '!=' => undef } }, { prefetch => 'cds_80s' })->all; - } 'prefetchy-fetchy-fetch?'; -} +lives_ok { + my @all_artists_with_80_cds = $schema->resultset("Artist")->search + ({ 'cds_80s.cdid' => { '!=' => undef } }, { prefetch => 'cds_80s' })->all; + + is_deeply + ([ sort ( map { $_->year } map { $_->cds_80s->all } @all_artists_with_80_cds ) ], + [ sort (1980..1989, 1980..1985) ], + '16 correct cds found' + ); +} 'prefetchy-fetchy-fetch'; my @all_artists_with_80_cds = $schema->resultset("Artist")->search ({ 'cds_80s.cdid' => { '!=' => undef } }, { join => 'cds_80s', distinct => 1 }); @@ -75,7 +78,6 @@ throws_ok { $artist->create_related('cds_90s', { title => 'related_creation 4', year => '2038' }); } qr/\Qunable to set_from_related - no simplified condition available for 'cds_90s'/, 'Create failed - non-simplified rel'; - # Do a self-join last-entry search my @last_track_ids; for my $cd ($schema->resultset('CD')->search ({}, { order_by => 'cdid'})->all) {