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 | |
10 | plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 2); |
11 | |
12 | my $schema = DBICTest->init_schema(); |
ff57f45b |
13 | $schema->storage->debug(1); |
a04af85f |
14 | my $no_prefetch = $schema->resultset('Artist')->search( |
25cac750 |
15 | undef, |
16 | { rows => 3 } |
a04af85f |
17 | ); |
18 | |
19 | my $use_prefetch = $schema->resultset('Artist')->search( |
25cac750 |
20 | undef, |
21 | { |
22 | prefetch => 'cds', |
23 | rows => 3 |
24 | } |
a04af85f |
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: { |
25cac750 |
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 | ); |
a04af85f |
43 | } |
25cac750 |
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. |