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');
-
-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)"
- );
-}
-__END__
-my $rs1 = $schema->resultset('Artist')->search(
- undef, {
-# join => 'cds',
- },
+is(
+ scalar ($no_prefetch->all),
+ scalar ($use_prefetch->all),
+ "Amount of returned rows is right"
);
-warn ${$rs1->as_query}->[0], $/;
-{ my @x = $rs1->all; warn "$#x\n"; }
-my $rs2 = $schema->resultset('Artist')->search(
- undef, {
- from => [{
- me => $rs1->as_query,
- }],
- prefetch => 'cds',
- },
+my $artist_many_cds = $schema->resultset('Artist')->search ( {}, {
+ join => 'cds',
+ group_by => 'me.artistid',
+ having => \ 'count(cds.cdid) > 1',
+})->first;
+
+
+$no_prefetch = $schema->resultset('Artist')->search(
+ { artistid => $artist_many_cds->id },
+ { rows => 1 }
);
-warn ${$rs2->as_query}->[0], $/;
-{ my @x = $rs2->all; warn "$#x\n"; }
+$use_prefetch = $no_prefetch->search ({}, { prefetch => 'cds' });
-__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.
+my $normal_artist = $no_prefetch->single;
+my $prefetch_artist = $use_prefetch->find({ name => $artist_many_cds->name });
+my $prefetch2_artist = $use_prefetch->first;
-This means that:
- $foo_rs->search(
- { ... },
- {
- 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)"
+);
-becomes:
- my $temp = $foo_rs->search(
- { ... },
- {
- join => 'bar',
- ...
- },
- );
- $foo_rs->storage->schema->resultset('foo')->search(
- undef,
- {
- from => [
- { me => $temp->as_query },
- ],
- prefetch => 'bar',
- },
- );
+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)"
+);
-Problem:
- * The prefetch->join change needs to happen ONLY IF there are conditions
- that depend on bar being joined.
- * How will this work when the $rs is further searched on? Those clauses
- need to be added to the subquery, not the outer one. This is particularly
- true if rows is added in the attribute later per the Pager.
+throws_ok (
+ sub { $use_prefetch->single },
+ qr/resultsets prefetching has_many/,
+ 'single() with multiprefetch is illegal',
+);