Commit | Line | Data |
a04af85f |
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 | |
5624ba1f |
10 | plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 3); |
a04af85f |
11 | |
12 | my $schema = DBICTest->init_schema(); |
13 | my $no_prefetch = $schema->resultset('Artist')->search( |
25cac750 |
14 | undef, |
15 | { rows => 3 } |
a04af85f |
16 | ); |
17 | |
18 | my $use_prefetch = $schema->resultset('Artist')->search( |
25cac750 |
19 | undef, |
20 | { |
21 | prefetch => 'cds', |
22 | rows => 3 |
23 | } |
a04af85f |
24 | ); |
25 | |
26 | my $no_prefetch_count = 0; |
27 | my $use_prefetch_count = 0; |
28 | |
29 | is($no_prefetch->count, $use_prefetch->count, '$no_prefetch->count == $use_prefetch->count'); |
30 | |
5624ba1f |
31 | $no_prefetch_count++ while $no_prefetch->next; |
32 | $use_prefetch_count++ while $use_prefetch->next; |
33 | is( |
34 | $no_prefetch_count, |
35 | $use_prefetch_count, |
36 | "manual row count confirms consistency" |
37 | . " (\$no_prefetch_count == $no_prefetch_count, " |
38 | . " \$use_prefetch_count == $use_prefetch_count)" |
39 | ); |
40 | |
41 | $no_prefetch = $schema->resultset('Artist')->search( |
42 | undef, |
43 | { rows => 1 } |
44 | ); |
45 | |
46 | $use_prefetch = $schema->resultset('Artist')->search( |
47 | undef, |
48 | { |
49 | prefetch => 'cds', |
50 | rows => 1 |
51 | } |
52 | ); |
53 | |
54 | my $prefetch_artist = $use_prefetch->first; |
55 | my $normal_artist = $no_prefetch->first; |
56 | |
57 | is( |
58 | $prefetch_artist->cds->count, |
59 | $normal_artist->cds->count, |
60 | "Count of child rel with prefetch + rows => 1 is right" |
61 | ); |
25cac750 |
62 | |
63 | __END__ |
64 | The fix is to, when using prefetch, take the query and put it into a subquery |
65 | joined to the tables we're prefetching from. This might result in the same |
66 | table being joined once in the main subquery and once in the main query. This |
67 | may actually resolve other, unknown edgecase bugs. It is also the right way |
68 | to do prefetching. Optimizations can come later. |
69 | |
70 | This means that: |
71 | $foo_rs->search( |
72 | { ... }, |
73 | { |
74 | prefetch => 'bar', |
75 | ... |
76 | }, |
77 | ); |
78 | |
79 | becomes: |
80 | my $temp = $foo_rs->search( |
81 | { ... }, |
82 | { |
83 | join => 'bar', |
84 | ... |
85 | }, |
86 | ); |
87 | $foo_rs->storage->schema->resultset('foo')->search( |
88 | undef, |
89 | { |
90 | from => [ |
91 | { me => $temp->as_query }, |
92 | ], |
93 | prefetch => 'bar', |
94 | }, |
95 | ); |
96 | |
97 | Problem: |
98 | * The prefetch->join change needs to happen ONLY IF there are conditions |
99 | that depend on bar being joined. |
5624ba1f |
100 | * Count of child rel. |
25cac750 |
101 | * How will this work when the $rs is further searched on? Those clauses |
102 | need to be added to the subquery, not the outer one. This is particularly |
103 | true if rows is added in the attribute later per the Pager. |