File: standard.t

package info (click to toggle)
libdbix-class-perl 0.082844-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,320 kB
  • sloc: perl: 27,215; sql: 322; sh: 29; makefile: 16
file content (272 lines) | stat: -rw-r--r-- 9,327 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
use strict;
use warnings;

use Test::More;
use Test::Exception;
use lib qw(t/lib);
use DBICTest;

my $schema = DBICTest->init_schema();

my $rs;
$schema->is_executed_querycount( sub {
  my $search = { 'artist.name' => 'Caterwauler McCrae' };
  my $attr = { prefetch => [ qw/artist liner_notes/ ],
             order_by => 'me.cdid' };

  $rs = $schema->resultset("CD")->search($search, $attr);
  my @cd = $rs->all;

  is($cd[0]->title, 'Spoonful of bees', 'First record returned ok');

  ok(!defined $cd[0]->liner_notes, 'No prefetch for NULL LEFT join');

  is($cd[1]->liner_notes->notes, 'Buy Whiskey!', 'Prefetch for present LEFT JOIN');

  is(ref $cd[1]->liner_notes, 'DBICTest::LinerNotes', 'Prefetch returns correct class');

  is($cd[2]->artist->name, 'Caterwauler McCrae', 'Prefetch on parent object ok');
}, 1, 'prefetch ran only 1 select statement');

# test for partial prefetch via columns attr
my $cd;
$schema->is_executed_querycount( sub {
  $cd = $schema->resultset('CD')->find(1,
    {
      columns => [qw/title artist artist.name/],
      join => { 'artist' => {} }
    }
  );
  is( $cd->artist->name, 'Caterwauler McCrae', 'single related column prefetched');
}, 1, 'manual prefetch ran only 1 select statement');

# start test for nested prefetch SELECT count
my $tag;
$schema->is_executed_querycount( sub {
  $rs = $schema->resultset('Tag')->search(
    { 'me.tagid' => 1 },
    {
      prefetch => { cd => 'artist' }
    }
  );

  $tag = $rs->first;

  is( $tag->cd->title, 'Spoonful of bees', 'step 1 ok for nested prefetch' );

  is( $tag->cd->artist->name, 'Caterwauler McCrae', 'step 2 ok for nested prefetch');
}, 1, 'nested prefetch ran exactly 1 select statement');


$schema->is_executed_querycount( sub {
  is($tag->search_related('cd')->search_related('artist')->first->name,
   'Caterwauler McCrae',
   'chained belongs_to->belongs_to search_related ok');
}, 0, 'chained search_related after belongs_to->belongs_to prefetch ran no queries');


$schema->is_executed_querycount( sub {
  $cd = $schema->resultset('CD')->find(1, { prefetch => 'artist' });

  is($cd->artist->name, 'Caterwauler McCrae', 'artist prefetched correctly on find');
}, 1, 'find with prefetch ran exactly 1 select statement');

$schema->is_executed_querycount( sub {
  $cd = $schema->resultset('CD')->find(1, { prefetch => { cd_to_producer => 'producer' }, order_by => 'producer.producerid' });

  is($cd->producers->first->name, 'Matt S Trout', 'many_to_many accessor ok');
}, 1, 'many_to_many accessor with nested prefetch ran exactly 1 query');

$schema->is_executed_querycount( sub {
  my $producers = $cd->search_related('cd_to_producer')->search_related('producer');

  is($producers->first->name, 'Matt S Trout', 'chained many_to_many search_related ok');
}, 0, 'chained search_related after many_to_many prefetch ran no queries');

$rs = $schema->resultset('Tag')->search(
  {},
  {
    join => { cd => 'artist' },
    prefetch => { cd => 'artist' }
  }
);

cmp_ok( $rs->count, '>=', 0, 'nested prefetch does not duplicate joins' );

my ($artist) = $schema->resultset("Artist")->search({ 'cds.year' => 2001 },
                 { order_by => 'artistid DESC', join => 'cds' });

is($artist->name, 'Random Boy Band', "Join search by object ok");

my @cds = $schema->resultset("CD")->search({ 'liner_notes.notes' => 'Buy Merch!' },
                               { join => 'liner_notes' });

cmp_ok(scalar @cds, '==', 1, "Single CD retrieved via might_have");

is($cds[0]->title, "Generic Manufactured Singles", "Correct CD retrieved");

my @artists = $schema->resultset("Artist")->search({ 'tags.tag' => 'Shiny' },
                                       { join => { 'cds' => 'tags' } });

cmp_ok( @artists, '==', 2, "two-join search ok" );

$rs = $schema->resultset("CD")->search(
  {},
  { group_by => [qw/ title me.cdid /] }
);

cmp_ok( $rs->count, '==', 5, "count() ok after group_by on main pk" );

cmp_ok( scalar $rs->all, '==', 5, "all() returns same count as count() after group_by on main pk" );

$rs = $schema->resultset("CD")->search(
  {},
  { join => [qw/ artist /], group_by => [qw/ artist.name /] }
);

cmp_ok( $rs->count, '==', 3, "count() ok after group_by on related column" );

$rs = $schema->resultset("Artist")->search({}, {
  join => [qw/ cds /],
  group_by => [qw/ me.name /],
  having => \[ 'MAX(cds.cdid) < ?', [ \'int' => 5 ] ],
});

cmp_ok( $rs->all, '==', 2, "results ok after group_by on related column with a having" );

$rs = $rs->search( undef, {  having =>{ 'count(*)'=> \'> 2' }});

cmp_ok( $rs->all, '==', 1, "count() ok after group_by on related column with a having" );

$rs = $schema->resultset("Artist")->search(
        { 'cds.title' => 'Spoonful of bees',
          'cds_2.title' => 'Forkful of bees' },
        { join => [ 'cds', 'cds' ] });

cmp_ok($rs->count, '==', 1, "single artist returned from multi-join");

is($rs->next->name, 'Caterwauler McCrae', "Correct artist returned");

$cd = $schema->resultset('Artist')->first->create_related('cds',
    {
    title   => 'Unproduced Single',
    year    => 2007
});

my $left_join = $schema->resultset('CD')->search(
    { 'me.cdid' => $cd->cdid },
    { prefetch => { cd_to_producer => 'producer' } }
);

cmp_ok($left_join, '==', 1, 'prefetch with no join record present');

my $tree_like;
$schema->is_executed_querycount( sub {
  $tree_like =
    $schema->resultset('TreeLike')->find(5,
      { join     => { parent => { parent => 'parent' } },
         prefetch => { parent => { parent => 'parent' } } });

  is($tree_like->name, 'quux', 'Bottom of tree ok');
  $tree_like = $tree_like->parent;
  is($tree_like->name, 'baz', 'First level up ok');
  $tree_like = $tree_like->parent;
  is($tree_like->name, 'bar', 'Second level up ok');
  $tree_like = $tree_like->parent;
  is($tree_like->name, 'foo', 'Third level up ok');

}, 1, 'Only one query run');

$tree_like = $schema->resultset('TreeLike')->search({'me.id' => 2});
$tree_like = $tree_like->search_related('children')->search_related('children')->search_related('children')->first;
is($tree_like->name, 'quux', 'Tree search_related ok');

$tree_like = $schema->resultset('TreeLike')->search_related('children',
    { 'children.id' => 3, 'children_2.id' => 4 },
    { prefetch => { children => 'children' } }
  )->first;
is( $tree_like->children->first->children->first->name, 'quux',
   'Tree search_related with prefetch ok');

$tree_like = $schema->resultset('TreeLike')->search(
    { 'children.id' => 3, 'children_2.id' => 6 },
    { join => [qw/children children children/] }
  )->search_related('children', { 'children_4.id' => 7 }, { prefetch => 'children' }
  )->first->children->first;
is( $tree_like->name, 'fong', 'Tree with multiple has_many joins ok');

$rs = $schema->resultset('Artist');
$rs->create({ artistid => 4, name => 'Unknown singer-songwriter' });
$rs->create({ artistid => 5, name => 'Emo 4ever' });
@artists = $rs->search(undef, { prefetch => 'cds', order_by => 'artistid' });
is(scalar @artists, 5, 'has_many prefetch with adjacent empty rows ok');

lives_ok { @artists = $rs->search(undef, {
        join => ['cds'],
        prefetch => [],
        rows => 20,
    });
} 'join and empty prefetch ok';

# -------------
#
# Tests for multilevel has_many prefetch

# artist resultsets - with and without prefetch
my $art_rs = $schema->resultset('Artist');
my $art_rs_pr = $art_rs->search(
    {},
    {
        join     => [ { cds => ['tracks'] } ],
        prefetch => [ { cds => ['tracks'] } ],
        cache    => 1 # last test needs this
    }
);

# This test does the same operation twice - once on a
# set of items fetched from the db with no prefetch of has_many rels
# The second prefetches 2 levels of has_many
# We check things are the same by comparing the name or title
# we build everything into a hash structure and compare the one
# from each rs to see what differs

sub make_hash_struc {
    my $rs = shift;

    my $struc = {};
    # all of these ought to work, but do not for some reason
    # a noop cloning search() pollution?
    #foreach my $art ( $rs->search({}, { order_by => 'me.artistid' })->all ) {
    #foreach my $art ( $rs->search({}, {})->all ) {
    #foreach my $art ( $rs->search()->all ) {
    foreach my $art ( $rs->all ) {
        foreach my $cd ( $art->cds ) {
            foreach my $track ( $cd->tracks ) {
                $struc->{ $art->name }{ $cd->title }{ $track->title }++;
            }
        }
    }
    return $struc;
}


my $prefetch_result;
$schema->is_executed_querycount( sub {
  $prefetch_result = make_hash_struc($art_rs_pr);
}, 1, 'nested prefetch across has_many->has_many ran exactly 1 query');

my $nonpre_result = make_hash_struc($art_rs);
is_deeply( $prefetch_result, $nonpre_result,
    'Compare 2 level prefetch result to non-prefetch result' );

$schema->is_executed_querycount( sub {
  is_deeply(
    [ sort map { $_->title } $art_rs_pr->search_related('cds')->search_related('tracks')->all ],
    [ 'Apiary', 'Beehind You', 'Boring Name', 'Boring Song', 'Fowlin', 'Howlin',
      'No More Ideas', 'Sad', 'Sticky Honey', 'Stripy', 'Stung with Success',
      'Suicidal', 'The Bees Knees', 'Under The Weather', 'Yowlin' ],
    'chained has_many->has_many search_related ok'
  );
}, 0, 'chained search_related after has_many->has_many prefetch ran no queries');

done_testing;