Fail early on literal-ordered complex prefetch without explicit group_by clause
[dbsrgits/DBIx-Class.git] / t / prefetch / with_limit.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 Test::Exception;
8 use lib qw(t/lib);
9 use DBICTest;
10 use DBIC::SqlMakerTest;
11
12 my $schema = DBICTest->init_schema();
13
14
15 my $no_prefetch = $schema->resultset('Artist')->search(
16   [   # search deliberately contrived
17     { 'artwork.cd_id' => undef },
18     { 'tracks.title' => { '!=' => 'blah-blah-1234568' }}
19   ],
20   { rows => 3, join => { cds => [qw/artwork tracks/] },
21  }
22 );
23
24 my $use_prefetch = $no_prefetch->search(
25   {},
26   {
27     select => ['me.artistid', 'me.name'],
28     as => ['artistid', 'name'],
29     prefetch => 'cds',
30     order_by => { -desc => 'name' },
31   }
32 );
33
34 is($no_prefetch->count, $use_prefetch->count, '$no_prefetch->count == $use_prefetch->count');
35 is(
36   scalar ($no_prefetch->all),
37   scalar ($use_prefetch->all),
38   "Amount of returned rows is right"
39 );
40
41 my $artist_many_cds = $schema->resultset('Artist')->search ( {}, {
42   join => 'cds',
43   group_by => 'me.artistid',
44   having => \ 'count(cds.cdid) > 1',
45 })->first;
46
47
48 $no_prefetch = $schema->resultset('Artist')->search(
49   { artistid => $artist_many_cds->id },
50   { rows => 1 }
51 );
52
53 $use_prefetch = $no_prefetch->search ({}, { prefetch => 'cds' });
54
55 my $normal_artist = $no_prefetch->single;
56 my $prefetch_artist = $use_prefetch->find({ name => $artist_many_cds->name });
57 my $prefetch2_artist = $use_prefetch->first;
58
59 is(
60   $prefetch_artist->cds->count,
61   $normal_artist->cds->count,
62   "Count of child rel with prefetch + rows => 1 is right (find)"
63 );
64 is(
65   $prefetch2_artist->cds->count,
66   $normal_artist->cds->count,
67   "Count of child rel with prefetch + rows => 1 is right (first)"
68 );
69
70 is (
71   scalar ($prefetch_artist->cds->all),
72   scalar ($normal_artist->cds->all),
73   "Amount of child rel rows with prefetch + rows => 1 is right (find)"
74 );
75 is (
76   scalar ($prefetch2_artist->cds->all),
77   scalar ($normal_artist->cds->all),
78   "Amount of child rel rows with prefetch + rows => 1 is right (first)"
79 );
80
81 throws_ok (
82   sub { $use_prefetch->single },
83   qr/resultsets prefetching has_many/,
84   'single() with multiprefetch is illegal',
85 );
86
87 throws_ok (
88   sub {
89     $use_prefetch->search(
90       {'tracks.title' => { '!=' => 'foo' }},
91       { order_by => \ 'some oddball literal sql', join => { cds => 'tracks' } }
92     )->next
93   }, qr/A required group_by clause could not be constructed automatically/,
94 );
95
96 my $artist = $use_prefetch->search({'cds.title' => $artist_many_cds->cds->first->title })->next;
97 is($artist->cds->count, 1, "count on search limiting prefetched has_many");
98
99 # try with double limit
100 my $artist2 = $use_prefetch->search({'cds.title' => { '!=' => $artist_many_cds->cds->first->title } })->slice (0,0)->next;
101 is($artist2->cds->count, 2, "count on search limiting prefetched has_many");
102
103 # make sure 1:1 joins do not force a subquery (no point to exercise the optimizer, if at all available)
104 # get cd's that have any tracks and their artists
105 my $single_prefetch_rs = $schema->resultset ('CD')->search (
106   { 'me.year' => 2010, 'artist.name' => 'foo' },
107   { prefetch => ['tracks', 'artist'], rows => 15 },
108 );
109 is_same_sql_bind (
110   $single_prefetch_rs->as_query,
111   '(
112     SELECT
113         me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track,
114         tracks.trackid, tracks.cd, tracks.position, tracks.title, tracks.last_updated_on, tracks.last_updated_at,
115         artist.artistid, artist.name, artist.rank, artist.charfield
116       FROM (
117         SELECT
118             me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
119           FROM cd me
120           JOIN artist artist ON artist.artistid = me.artist
121         WHERE ( ( artist.name = ? AND me.year = ? ) )
122         LIMIT 15
123       ) me
124       LEFT JOIN track tracks
125         ON tracks.cd = me.cdid
126       JOIN artist artist
127         ON artist.artistid = me.artist
128     WHERE ( ( artist.name = ? AND me.year = ? ) )
129     ORDER BY tracks.cd
130   )',
131   [
132     [ 'artist.name' => 'foo' ],
133     [ 'me.year'     => 2010  ],
134     [ 'artist.name' => 'foo' ],
135     [ 'me.year'     => 2010  ],
136   ],
137   'No grouping of non-multiplying resultsets',
138 );
139
140 done_testing;