Merge 'trunk' into 'prefetch'
[dbsrgits/DBIx-Class.git] / t / 98rows_prefetch.t
1 # Test to ensure we get a consistent result set wether or not we use the
2 # prefetch option in combination rows (LIMIT).
3 use strict;
4 use warnings;
5
6 use Test::More;
7 use lib qw(t/lib);
8 use DBICTest;
9
10 plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 2);
11
12 my $schema = DBICTest->init_schema();
13 $schema->storage->debug(1);
14 my $no_prefetch = $schema->resultset('Artist')->search(
15   undef,
16   { rows => 3 }
17 );
18
19 my $use_prefetch = $schema->resultset('Artist')->search(
20   undef,
21   {
22     prefetch => 'cds',
23     rows     => 3
24   }
25 );
26
27 my $no_prefetch_count  = 0;
28 my $use_prefetch_count = 0;
29
30 is($no_prefetch->count, $use_prefetch->count, '$no_prefetch->count == $use_prefetch->count');
31
32 TODO: {
33   local $TODO = "This is a difficult bug to fix, workaround is not to use prefetch with rows";
34   $no_prefetch_count++  while $no_prefetch->next;
35   $use_prefetch_count++ while $use_prefetch->next;
36   is(
37     $no_prefetch_count,
38     $use_prefetch_count,
39     "manual row count confirms consistency"
40     . " (\$no_prefetch_count == $no_prefetch_count, "
41     . " \$use_prefetch_count == $use_prefetch_count)"
42   );
43 }
44 __END__
45 my $rs1 = $schema->resultset('Artist')->search(
46     undef, {
47 #        join => 'cds',
48     },
49 );
50 warn ${$rs1->as_query}->[0], $/;
51 { my @x = $rs1->all; warn "$#x\n"; }
52
53 my $rs2 = $schema->resultset('Artist')->search(
54     undef, {
55         from => [{
56             me => $rs1->as_query,
57         }],
58         prefetch => 'cds',
59     },
60 );
61
62 warn ${$rs2->as_query}->[0], $/;
63 { my @x = $rs2->all; warn "$#x\n"; }
64
65 __END__
66 The fix is to, when using prefetch, take the query and put it into a subquery
67 joined to the tables we're prefetching from. This might result in the same
68 table being joined once in the main subquery and once in the main query. This
69 may actually resolve other, unknown edgecase bugs. It is also the right way
70 to do prefetching. Optimizations can come later.
71
72 This means that:
73   $foo_rs->search(
74     { ... },
75     {
76       prefetch => 'bar',
77       ...
78     },
79   );
80
81 becomes:
82   my $temp = $foo_rs->search(
83     { ... },
84     {
85       join => 'bar',
86       ...
87     },
88   );
89   $foo_rs->storage->schema->resultset('foo')->search(
90     undef,
91     {
92       from => [
93         { me => $temp->as_query },
94       ],
95       prefetch => 'bar',
96     },
97   );
98
99 Problem:
100   * The prefetch->join change needs to happen ONLY IF there are conditions
101     that depend on bar being joined.
102   * How will this work when the $rs is further searched on? Those clauses
103     need to be added to the subquery, not the outer one. This is particularly
104     true if rows is added in the attribute later per the Pager.