single() throws with has_many prefetch
[dbsrgits/DBIx-Class-Historic.git] / t / prefetch / rows_bug.t
index 821c84e..6e849f2 100644 (file)
@@ -4,77 +4,82 @@ use strict;
 use warnings;
 
 use Test::More;
+use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
-plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 2);
+plan tests => 7;
 
 my $schema = DBICTest->init_schema();
+
+
 my $no_prefetch = $schema->resultset('Artist')->search(
   undef,
   { rows => 3 }
 );
 
 my $use_prefetch = $schema->resultset('Artist')->search(
-  undef,
+  [   # search deliberately contrived
+    { 'artwork.cd_id' => undef },
+    { 'tracks.title' => { '!=' => 'blah-blah-1234568' }}
+  ],
   {
     prefetch => 'cds',
-    rows     => 3
+    join => { cds => [qw/artwork tracks/] },
+    rows     => 3,
+    order_by => { -desc => 'name' },
   }
 );
 
-my $no_prefetch_count  = 0;
-my $use_prefetch_count = 0;
-
 is($no_prefetch->count, $use_prefetch->count, '$no_prefetch->count == $use_prefetch->count');
+is(
+  scalar ($no_prefetch->all),
+  scalar ($use_prefetch->all),
+  "Amount of returned rows is right"
+);
+
+my $artist_many_cds = $schema->resultset('Artist')->search ( {}, {
+  join => 'cds',
+  group_by => 'me.artistid',
+  having => \ 'count(cds.cdid) > 1',
+})->first;
+
 
-TODO: {
-  local $TODO = "This is a difficult bug to fix, workaround is not to use prefetch with rows";
-  $no_prefetch_count++  while $no_prefetch->next;
-  $use_prefetch_count++ while $use_prefetch->next;
-  is(
-    $no_prefetch_count,
-    $use_prefetch_count,
-    "manual row count confirms consistency"
-    . " (\$no_prefetch_count == $no_prefetch_count, "
-    . " \$use_prefetch_count == $use_prefetch_count)"
-  );
-}
+$no_prefetch = $schema->resultset('Artist')->search(
+  { artistid => $artist_many_cds->id },
+  { rows => 1 }
+);
 
-__END__
-The fix is to, when using prefetch, take the query and put it into a subquery
-joined to the tables we're prefetching from. This might result in the same
-table being joined once in the main subquery and once in the main query. This
-may actually resolve other, unknown edgecase bugs. It is also the right way
-to do prefetching. Optimizations can come later.
+$use_prefetch = $no_prefetch->search ({}, { prefetch => 'cds' });
 
-This means that:
-  $foo_rs->search(
-    { ... },
-    {
-      prefetch => 'bar',
-      ...
-    },
-  );
+my $normal_artist = $no_prefetch->single;
+my $prefetch_artist = $use_prefetch->find({ name => $artist_many_cds->name });
+my $prefetch2_artist = $use_prefetch->first;
 
-becomes:
-  my $temp = $foo_rs->search(
-    { ... },
-    {
-      join => 'bar',
-      ...
-    },
-  );
-  $foo_rs->storage->schema->resultset('foo')->search(
-    undef,
-    {
-      from => [
-        { me => $temp->as_query },
-      ],
-      prefetch => 'bar',
-    },
-  );
+is(
+  $prefetch_artist->cds->count,
+  $normal_artist->cds->count,
+  "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)"
+);
 
-Problem:
-  * The prefetch->join change needs to happen ONLY IF there are conditions
-    that depend on bar being joined.
+is (
+  scalar ($prefetch_artist->cds->all),
+  scalar ($normal_artist->cds->all),
+  "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',
+);