support for prefetch from resultsource using extended_rels
Daniel Ruoso [Mon, 22 Nov 2010 15:12:17 +0000 (12:12 -0300)]
lib/DBIx/Class/ResultSource.pm
t/relationship/custom.t

index 4f41baa..780aaa9 100644 (file)
@@ -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
index 3b58926..369aeb0 100644 (file)
@@ -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) {