single() throws with has_many prefetch
Peter Rabbitson [Fri, 19 Jun 2009 13:39:43 +0000 (13:39 +0000)]
lib/DBIx/Class/ResultSet.pm
t/prefetch/rows_bug.t

index 2160cf0..6faf118 100644 (file)
@@ -698,10 +698,14 @@ a warning:
 
   Query returned more than one row
 
-In this case, you should be using L</first> or L</find> instead, or if you really
+In this case, you should be using L</next> or L</find> instead, or if you really
 know what you are doing, use the L</rows> attribute to explicitly limit the size
 of the resultset.
 
+This method will also throw an exception if it is called on a resultset prefetching
+has_many, as such a prefetch implies fetching multiple rows from the database in
+order to assemble the resulting object.
+
 =back
 
 =cut
@@ -714,6 +718,12 @@ sub single {
 
   my $attrs = $self->_resolved_attrs_copy;
 
+  if (keys %{$attrs->{collapse}}) {
+    $self->throw_exception(
+      'single() can not be used on resultsets prefetching has_many. Use find( \%cond ) or next() instead'
+    );
+  }
+
   if ($where) {
     if (defined $attrs->{where}) {
       $attrs->{where} = {
index be3fff1..6e849f2 100644 (file)
@@ -4,10 +4,11 @@ use strict;
 use warnings;
 
 use Test::More;
+use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
-plan tests => 4;
+plan tests => 7;
 
 my $schema = DBICTest->init_schema();
 
@@ -49,24 +50,36 @@ $no_prefetch = $schema->resultset('Artist')->search(
   { rows => 1 }
 );
 
-$use_prefetch = $schema->resultset('Artist')->search(
-  { artistid => $artist_many_cds->id },
-  {
-    prefetch => 'cds',
-    rows     => 1
-  }
-);
+$use_prefetch = $no_prefetch->search ({}, { prefetch => 'cds' });
 
-my $prefetch_artist = $use_prefetch->first;
-my $normal_artist = $no_prefetch->first;
+my $normal_artist = $no_prefetch->single;
+my $prefetch_artist = $use_prefetch->find({ name => $artist_many_cds->name });
+my $prefetch2_artist = $use_prefetch->first;
 
 is(
   $prefetch_artist->cds->count,
   $normal_artist->cds->count,
-  "Count of child rel with prefetch + rows => 1 is right"
+  "Count of child rel with prefetch + rows => 1 is right (find)"
+);
+is(
+  $prefetch2_artist->cds->count,
+  $normal_artist->cds->count,
+  "Count of child rel with prefetch + rows => 1 is right (first)"
 );
+
 is (
   scalar ($prefetch_artist->cds->all),
   scalar ($normal_artist->cds->all),
-  "Amount of child rel rows with prefetch + rows => 1 is right"
+  "Amount of child rel rows with prefetch + rows => 1 is right (find)"
+);
+is (
+  scalar ($prefetch2_artist->cds->all),
+  scalar ($normal_artist->cds->all),
+  "Amount of child rel rows with prefetch + rows => 1 is right (first)"
+);
+
+throws_ok (
+  sub { $use_prefetch->single },
+  qr/resultsets prefetching has_many/,
+  'single() with multiprefetch is illegal',
 );