Move scary stuff to its own class
[dbsrgits/DBIx-Class.git] / t / prefetch / _internals.t
1 use strict;
2 use warnings;
3
4 use Test::More;
5 use lib qw(t/lib);
6 use DBICTest;
7 use B::Deparse;
8
9
10 my $schema = DBICTest->init_schema(no_deploy => 1);
11
12 my ($as, $vals, @pairs);
13
14 # artwork-artist deliberately mixed around
15 @pairs = (
16   'artwork_to_artist.artist_id' => '2',
17
18   'cd_id' => '1',
19
20   'artwork_to_artist.artwork_cd_id' => '1',
21
22   'cd.artist' => '1',
23   'cd.cdid' => '1',
24   'cd.title' => 'Spoonful of bees',
25
26   'cd.artist.artistid' => '7',
27   'cd.artist.name' => 'Caterwauler McCrae',
28   'artwork_to_artist.artist.name' => 'xenowhinycide',
29 );
30 while (@pairs) {
31   push @$as, shift @pairs;
32   push @$vals, shift @pairs;
33 }
34
35 =begin
36
37 my $parser = $schema->source ('Artwork')->_mk_row_parser({
38   inflate_map => $as,
39   collapse => 1,
40 });
41
42 is_deeply (
43   $parser->($vals),
44   [
45     {
46       cd_id => 1,
47     },
48
49     {
50       artwork_to_artist => [
51         {
52           artist_id => 2,
53           artwork_cd_id => 1,
54         },
55         {
56           artist => [
57             {
58               name => 'xenowhinycide',
59             },
60             undef,
61             [ 2, 1 ], # inherited from artwork_to_artist (child-parent definition)
62           ],
63         },
64         [ 2, 1 ]  # artwork_to_artist own data, in selection order
65       ],
66
67       cd => [
68         {
69           artist => 1,
70           cdid => 1,
71           title => 'Spoonful of bees',
72         },
73         {
74           artist => [
75             {
76               artistid => 7,
77               name => 'Caterwauler McCrae',
78             },
79             undef,
80             [ 7 ], # our own id
81           ]
82         },
83         [ 1 ], # our cdid fk
84       ]
85     },
86     [ 1 ], # our id
87   ],
88   'generated row parser works as expected',
89 );
90
91 #=begin
92
93 undef $_ for ($as, $vals);
94 @pairs = (
95   'name' => 'Caterwauler McCrae',
96   'cds.tracks.cd' => '3',
97   'cds.tracks.title' => 'Fowlin',
98   'cds.tracks.cd_single.title' => 'Awesome single',
99 );
100 while (@pairs) {
101   push @$as, shift @pairs;
102   push @$vals, shift @pairs;
103 }
104 $parser = $schema->source ('Artist')->_mk_row_parser($as);
105
106 is_deeply (
107   $parser->($vals),
108   [
109     {
110       name => 'Caterwauler McCrae'
111     },
112     {
113       cds => [
114         {},
115         {
116           tracks => [
117             {
118               cd => 3,
119               title => 'Fowlin'
120             },
121             {
122               cd_single => [
123                 {
124                   title => 'Awesome single',
125                 },
126               ],
127             },
128           ]
129         }
130       ]
131     }
132   ],
133   'generated parser works as expected over missing joins (no collapse)',
134 );
135
136 =cut
137
138 undef $_ for ($as, $vals);
139 @pairs = (
140     'tracks.lyrics.lyric_versions.text'                => 'unique when combined with the lyric collapsable by the 1:1 tracks-parent',
141     'existing_single_track.cd.artist.artistid'         => 'artist_id (gives uniq. to its entire parent chain)',
142     'existing_single_track.cd.artist.cds.year'         => 'non-unique cds col (year)',
143     'year'                                             => 'non unique main year',
144     'genreid'                                          => 'non-unique/nullable main genid',
145     'tracks.title'                                     => 'non-unique title (missing multicol const. part)',
146     'existing_single_track.cd.artist.cds.cdid'         => 'cds unique id col to give uniquiness to ...tracks.title below',
147     'latest_cd'                                        => 'random function (not a colname)',
148     'existing_single_track.cd.artist.cds.tracks.title' => 'unique track title (when combined with ...cds.cdid above)',
149     'existing_single_track.cd.artist.cds.genreid'      => 'nullable cds col (genreid)',
150 );
151 while (@pairs) {
152   push @$as, shift @pairs;
153   push @$vals, shift @pairs;
154 }
155
156 is_deeply (
157   $schema->source ('CD')->_resolve_collapse ( { map { $as->[$_] => $_ } (0 .. $#$as) } ),
158   {
159     -node_index => 1,
160     -node_id => [ 1 ], # existing_single_track.cd.artist.artistid
161     -branch_id => [ 0, 1, 5, 6, 8 ],
162
163     existing_single_track => {
164       -node_index => 2,
165       -node_id => [ 1 ], # existing_single_track.cd.artist.artistid
166       -branch_id => [ 1, 6, 8 ],
167       -is_single => 1,
168
169       cd => {
170         -node_index => 3,
171         -node_id => [ 1 ], # existing_single_track.cd.artist.artistid
172         -branch_id => [ 1, 6, 8 ],
173         -is_single => 1,
174
175         artist => {
176           -node_index => 4,
177           -node_id => [ 1 ], # existing_single_track.cd.artist.artistid
178           -branch_id => [ 1, 6, 8 ],
179           -is_single => 1,
180
181           cds => {
182             -node_index => 5,
183             -node_id => [ 6 ], # existing_single_track.cd.artist.cds.cdid
184             -branch_id => [ 6, 8 ],
185             -is_optional => 1,
186
187             tracks => {
188               -node_index => 6,
189               -node_id => [ 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title
190               -branch_id => [ 6, 8 ],
191               -is_optional => 1,
192             }
193           }
194         }
195       }
196     },
197     tracks => {
198       -node_index => 7,
199       -node_id => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title
200       -branch_id => [ 0, 1, 5 ],
201       -is_optional => 1,
202
203       lyrics => {
204         -node_index => 8,
205         -node_id => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title
206         -branch_id => [ 0, 1, 5 ],
207         -is_single => 1,
208         -is_optional => 1,
209
210         lyric_versions => {
211           -node_index => 9,
212           -node_id => [ 0, 1, 5 ], # tracks.lyrics.lyric_versions.text, existing_single_track.cd.artist.artistid, tracks.title
213           -branch_id => [ 0, 1, 5 ],
214           -is_optional => 1,
215         },
216       },
217     }
218   },
219   'Correct collapse map constructed',
220 );
221
222 done_testing;
223 __END__
224 =cut
225
226 my $parser = $schema->source ('CD')->_mk_row_parser ({ inflate_map => $as, collapse => 1 });
227
228 =begin
229
230 is_deeply (
231   $parser->($vals),
232   [
233     {
234       latest_cd => 'random function (not a colname)',
235       year => 'non unique main year',
236       genreid => 'non-unique/nullable main genid'
237     },
238     {
239       existing_single_track => [
240         {},
241         {
242           cd => [
243             {},
244             {
245               artist => [
246                 { artistid => 'artist_id (gives uniq. to its entire parent chain)' },
247                 {
248                   cds => [
249                     {
250                       cdid => 'cds unique id col to give uniquiness to ...tracks.title below',
251                       year => 'non-unique cds col (year)',
252                       genreid => 'nullable cds col (genreid)'
253                     },
254                     {
255                       tracks => [
256                         {
257                           title => 'unique track title (when combined with ...cds.cdid above)'
258                         },
259                         undef,
260                         [
261                           'cds unique id col to give uniquiness to ...tracks.title below',
262                           'unique track title (when combined with ...cds.cdid above)',
263                         ],
264                       ]
265                     },
266                     [ 'cds unique id col to give uniquiness to ...tracks.title below' ],
267                   ]
268                 },
269                 [ 'artist_id (gives uniq. to its entire parent chain)' ],
270               ]
271             },
272             [ 'artist_id (gives uniq. to its entire parent chain)' ],
273           ]
274         },
275         [ 'artist_id (gives uniq. to its entire parent chain)' ],
276       ],
277       tracks => [
278         {
279           title => 'non-unique title (missing multicol const. part)'
280         },
281         {
282           lyrics => [
283             {},
284             {
285               lyric_versions => [
286                 {
287                   text => 'unique when combined with the lyric collapsable by the 1:1 tracks-parent',
288                 },
289                 undef,
290                 [
291                   'unique when combined with the lyric collapsable by the 1:1 tracks-parent',
292                   'artist_id (gives uniq. to its entire parent chain)',
293                   'non-unique title (missing multicol const. part)',
294                 ],
295               ],
296             },
297             [
298               'artist_id (gives uniq. to its entire parent chain)',
299               'non-unique title (missing multicol const. part)',
300             ],
301           ],
302         },
303         [
304           'artist_id (gives uniq. to its entire parent chain)',
305           'non-unique title (missing multicol const. part)',
306         ],
307       ],
308     },
309     [ 'artist_id (gives uniq. to its entire parent chain)' ],
310   ],
311   'Proper row parser constructed',
312 );
313
314 =cut
315
316 # For extra insanity test/showcase the parser's guts:
317 my $deparser = B::Deparse->new;
318 is (
319   $deparser->coderef2text ($parser),
320   $deparser->coderef2text ( sub { package DBIx::Class::ResultSource;
321     my $rows = [];
322     while (1) {
323       my $r = (shift @{$_[0]->{row_stash}}) || ($_[0]->{next_row} and $_[0]->{next_row}->()) || last;
324
325     }
326     return $rows
327
328
329     [
330       {
331         genreid => $_[0][4],
332         latest_cd => $_[0][7],
333         year => $_[0][3]
334       },
335       {
336
337         existing_single_track => [
338           {},
339           {
340             cd => [
341               {},
342               {
343                 artist => [
344                   {
345                     artistid => $_[0][1]
346                   },
347                   {
348
349                     !defined($_[0][6]) ? () : (
350                     cds => [
351                       {
352                         cdid => $_[0][6],
353                         genreid => $_[0][9],
354                         year => $_[0][2]
355                       },
356                       {
357
358                         !defined($_[0][8]) ? () : (
359                         tracks => [
360                           {
361                             title => $_[0][8]
362                           },
363                           undef,
364                           [ $_[0][6], $_[0][8] ]
365                         ])
366
367                       },
368                       [ $_[0][6] ]
369                     ]),
370
371                   },
372                   [ $_[0][1] ],
373                 ],
374               },
375               [ $_[0][1] ],
376             ],
377           },
378           [ $_[0][1] ],
379         ],
380
381         !defined($_[0][5]) ? () : (
382         tracks => [
383           {
384             title => $_[0][5],
385           },
386           {
387
388             lyrics => [
389               {},
390               {
391
392                 !defined($_[0][0]) ? () : (
393                 lyric_versions => [
394                   {
395                     text => $_[0][0]
396                   },
397                   undef,
398                   [ $_[0][0], $_[0][1], $_[0][5] ],
399                 ]),
400
401               },
402               [ $_[0][1], $_[0][5] ],
403             ],
404
405           },
406           [ $_[0][1], $_[0][5] ],
407         ]),
408       },
409       [ $_[0][1] ],
410     ];
411   }),
412   'Deparsed version of the parser coderef looks correct',
413 );
414
415 done_testing;