Commit | Line | Data |
4e9fc3f3 |
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 | |
7d5371dc |
9 | # globally set for the rest of test |
10 | # the rowparser maker does not order its hashes by default for the miniscule |
11 | # speed gain. But it does not disable sorting either - for this test |
12 | # everything will be ordered nicely, and the hash randomization of 5.18 |
13 | # will not trip up anything |
14 | use Data::Dumper; |
15 | $Data::Dumper::Sortkeys = 1; |
16 | |
4e9fc3f3 |
17 | my $schema = DBICTest->init_schema(no_deploy => 1); |
ce556881 |
18 | my $infmap = [qw/ |
19 | single_track.cd.artist.name |
20 | year |
21 | /]; |
4e9fc3f3 |
22 | |
23 | is_same_src ( |
24 | $schema->source ('CD')->_mk_row_parser({ |
25 | inflate_map => $infmap, |
26 | }), |
27 | '$_ = [ |
28 | { year => $_->[1] }, |
52864fbd |
29 | { single_track => ( ! defined( $_->[0]) ) |
30 | ? bless( [ |
4e9fc3f3 |
31 | undef, |
52864fbd |
32 | { cd => [ |
33 | undef, |
34 | { artist => [ |
35 | { name => $_->[0] }, |
36 | ] }, |
4e9fc3f3 |
37 | ] }, |
52864fbd |
38 | ], __NBC__ ) |
39 | : [ |
40 | undef, |
41 | { cd => [ |
42 | undef, |
43 | { artist => [ |
44 | { name => $_->[0] }, |
45 | ] }, |
46 | ] }, |
47 | ] |
48 | }, |
4e9fc3f3 |
49 | ] for @{$_[0]}', |
50 | 'Simple 1:1 descending non-collapsing parser', |
51 | ); |
52 | |
53 | $infmap = [qw/ |
3faac878 |
54 | single_track.cd.artist.cds.tracks.title |
4e9fc3f3 |
55 | single_track.cd.artist.artistid |
56 | year |
4e9fc3f3 |
57 | single_track.cd.artist.cds.cdid |
58 | title |
59 | artist |
60 | /]; |
4e9fc3f3 |
61 | |
ce556881 |
62 | is_same_src ( |
63 | $schema->source ('CD')->_mk_row_parser({ |
ce556881 |
64 | inflate_map => $infmap, |
65 | }), |
66 | '$_ = [ |
67 | { artist => $_->[5], title => $_->[4], year => $_->[2] }, |
68 | { |
52864fbd |
69 | single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) ) |
70 | ? bless( [ |
71 | undef, |
72 | { |
73 | cd => [ |
74 | undef, |
75 | { |
76 | artist => [ |
77 | { artistid => $_->[1] }, |
78 | { |
79 | cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) |
80 | ? bless ([ |
81 | { cdid => $_->[3] }, |
82 | { |
83 | tracks => ( ! defined $_->[0] ) |
84 | ? bless ( [{ title => $_->[0] }], __NBC__ ) |
85 | : [{ title => $_->[0] }] |
86 | } |
87 | ], __NBC__) |
88 | : [ |
89 | { cdid => $_->[3] }, |
90 | { |
91 | tracks => ( ! defined $_->[0] ) |
92 | ? bless ( [{ title => $_->[0] }], __NBC__ ) |
93 | : [{ title => $_->[0] }] |
94 | } |
95 | ] |
96 | } |
97 | ] |
98 | } |
99 | ] |
100 | } |
101 | ], __NBC__) |
102 | : [ |
ce556881 |
103 | undef, |
104 | { |
105 | cd => [ |
106 | undef, |
107 | { |
108 | artist => [ |
109 | { artistid => $_->[1] }, |
110 | { |
52864fbd |
111 | cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) |
112 | ? bless ([ |
113 | { cdid => $_->[3] }, |
114 | { |
115 | tracks => ( ! defined $_->[0] ) |
116 | ? bless ( [{ title => $_->[0] }], __NBC__ ) |
117 | : [{ title => $_->[0] }] |
118 | } |
119 | ], __NBC__) |
120 | : [ |
ce556881 |
121 | { cdid => $_->[3] }, |
122 | { |
52864fbd |
123 | tracks => ( ! defined $_->[0] ) |
124 | ? bless ( [{ title => $_->[0] }], __NBC__ ) |
125 | : [{ title => $_->[0] }] |
ce556881 |
126 | } |
52864fbd |
127 | ] |
ce556881 |
128 | } |
129 | ] |
130 | } |
131 | ] |
132 | } |
52864fbd |
133 | ] |
ce556881 |
134 | } |
135 | ] for @{$_[0]}', |
52864fbd |
136 | '1:1 descending non-collapsing parser terminating with chained 1:M:M', |
ce556881 |
137 | ); |
138 | |
139 | is_same_src ( |
140 | $schema->source ('CD')->_mk_row_parser({ |
ce556881 |
141 | hri_style => 1, |
142 | inflate_map => $infmap, |
143 | }), |
144 | '$_ = { |
145 | artist => $_->[5], title => $_->[4], year => $_->[2], |
146 | |
52864fbd |
147 | ( single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) ) |
148 | ? undef |
149 | : { |
ce556881 |
150 | cd => |
151 | { |
152 | artist => { |
153 | artistid => $_->[1], |
52864fbd |
154 | ( cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) |
155 | ? undef |
156 | : { |
ce556881 |
157 | cdid => $_->[3], |
52864fbd |
158 | ( tracks => ( ! defined $_->[0] ) |
159 | ? undef |
160 | : { title => $_->[0] } |
161 | ) |
ce556881 |
162 | } |
52864fbd |
163 | ) |
ce556881 |
164 | } |
165 | } |
166 | } |
52864fbd |
167 | ) |
ce556881 |
168 | } for @{$_[0]}', |
52864fbd |
169 | '1:1 descending non-collapsing HRI-direct parser terminating with chained 1:M:M', |
ce556881 |
170 | ); |
171 | |
172 | |
173 | |
4e9fc3f3 |
174 | is_deeply ( |
3faac878 |
175 | ($schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} })), |
4e9fc3f3 |
176 | { |
9f98c4b2 |
177 | -identifying_columns => [ 4, 5 ], |
4e9fc3f3 |
178 | |
179 | single_track => { |
a0726a33 |
180 | -identifying_columns => [ 1, 4, 5 ], |
4e9fc3f3 |
181 | -is_optional => 1, |
182 | -is_single => 1, |
183 | |
184 | cd => { |
a0726a33 |
185 | -identifying_columns => [ 1, 4, 5 ], |
4e9fc3f3 |
186 | -is_single => 1, |
187 | |
188 | artist => { |
a0726a33 |
189 | -identifying_columns => [ 1, 4, 5 ], |
4e9fc3f3 |
190 | -is_single => 1, |
191 | |
192 | cds => { |
a0726a33 |
193 | -identifying_columns => [ 1, 3, 4, 5 ], |
4e9fc3f3 |
194 | -is_optional => 1, |
195 | |
196 | tracks => { |
a0726a33 |
197 | -identifying_columns => [ 0, 1, 3, 4, 5 ], |
4e9fc3f3 |
198 | -is_optional => 1, |
199 | }, |
200 | }, |
201 | }, |
202 | }, |
203 | }, |
204 | }, |
205 | 'Correct collapse map for 1:1 descending chain terminating with chained 1:M:M' |
206 | ); |
207 | |
208 | is_same_src ( |
209 | $schema->source ('CD')->_mk_row_parser({ |
210 | inflate_map => $infmap, |
211 | collapse => 1, |
212 | }), |
9f98c4b2 |
213 | ' my($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0, 0); |
4e9fc3f3 |
214 | |
9f98c4b2 |
215 | while ($cur_row_data = ( |
4e9fc3f3 |
216 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
217 | || |
218 | ( $_[1] and $_[1]->() ) |
219 | ) { |
220 | |
9f98c4b2 |
221 | $cur_row_ids{$_} = defined $cur_row_data->[$_] ? $cur_row_data->[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
a0726a33 |
222 | for (0, 1, 3, 4, 5); |
4e9fc3f3 |
223 | |
3faac878 |
224 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
9f98c4b2 |
225 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
226 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} ); |
4e9fc3f3 |
227 | |
3faac878 |
228 | # the rowdata itself for root node |
9f98c4b2 |
229 | $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} ||= [{ artist => $cur_row_data->[5], title => $cur_row_data->[4], year => $cur_row_data->[2] }]; |
3faac878 |
230 | |
231 | # prefetch data of single_track (placed in root) |
52864fbd |
232 | $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track} ||= $collapse_idx[1]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} ||= []; |
233 | defined($cur_row_data->[1]) or bless( $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track}, __NBC__ ); |
3faac878 |
234 | |
235 | # prefetch data of cd (placed in single_track) |
52864fbd |
236 | $collapse_idx[1]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} ||= []; |
4e9fc3f3 |
237 | |
3faac878 |
238 | # prefetch data of artist ( placed in single_track->cd) |
a0726a33 |
239 | $collapse_idx[2]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} ||= [{ artistid => $cur_row_data->[1] }]; |
3faac878 |
240 | |
241 | # prefetch data of cds (if available) |
ce556881 |
242 | (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} ) |
243 | and |
244 | push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}}, ( |
245 | $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ cdid => $cur_row_data->[3] }] |
246 | ); |
52864fbd |
247 | defined($cur_row_data->[3]) or bless( $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}, __NBC__ ); |
4e9fc3f3 |
248 | |
3faac878 |
249 | # prefetch data of tracks (if available) |
ce556881 |
250 | (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} ) |
251 | and |
252 | push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}}, ( |
253 | $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[0] }] |
254 | ); |
52864fbd |
255 | defined($cur_row_data->[0]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}, __NBC__ ); |
4e9fc3f3 |
256 | |
9f98c4b2 |
257 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} |
4e9fc3f3 |
258 | if $is_new_res; |
259 | } |
260 | splice @{$_[0]}, $result_pos; |
261 | ', |
262 | 'Same 1:1 descending terminating with chained 1:M:M but with collapse', |
263 | ); |
264 | |
ce556881 |
265 | is_same_src ( |
266 | $schema->source ('CD')->_mk_row_parser({ |
267 | inflate_map => $infmap, |
268 | collapse => 1, |
ce556881 |
269 | hri_style => 1, |
270 | }), |
7596ddca |
271 | ' my($rows_pos, $result_pos, $cur_row_data, @collapse_idx, $is_new_res) = (0, 0); |
ce556881 |
272 | |
273 | while ($cur_row_data = ( |
274 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
275 | || |
276 | ( $_[1] and $_[1]->() ) |
277 | ) { |
278 | |
ce556881 |
279 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
280 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
7596ddca |
281 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]} ); |
ce556881 |
282 | |
283 | # the rowdata itself for root node |
7596ddca |
284 | $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]} ||= { artist => $cur_row_data->[5], title => $cur_row_data->[4], year => $cur_row_data->[2] }; |
ce556881 |
285 | |
286 | # prefetch data of single_track (placed in root) |
7596ddca |
287 | (! defined($cur_row_data->[1]) ) ? $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]}{single_track} = undef : do { |
288 | $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]}{single_track} ||= $collapse_idx[1]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}; |
ce556881 |
289 | |
7596ddca |
290 | # prefetch data of cd (placed in single_track) |
291 | $collapse_idx[1]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cd} ||= $collapse_idx[2]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}; |
ce556881 |
292 | |
7596ddca |
293 | # prefetch data of artist ( placed in single_track->cd) |
294 | $collapse_idx[2]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{artist} ||= $collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]} ||= { artistid => $cur_row_data->[1] }; |
ce556881 |
295 | |
7596ddca |
296 | # prefetch data of cds (if available) |
297 | (! defined $cur_row_data->[3] ) ? $collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cds} = [] : do { |
ce556881 |
298 | |
7596ddca |
299 | (! $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} ) |
300 | and |
301 | push @{$collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cds}}, ( |
302 | $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} = { cdid => $cur_row_data->[3] } |
303 | ); |
ce556881 |
304 | |
7596ddca |
305 | # prefetch data of tracks (if available) |
306 | ( ! defined $cur_row_data->[0] ) ? $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]}{tracks} = [] : do { |
307 | |
308 | (! $collapse_idx[5]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} ) |
309 | and |
310 | push @{$collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]}{tracks}}, ( |
311 | $collapse_idx[5]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} = { title => $cur_row_data->[0] } |
312 | ); |
313 | }; |
314 | }; |
315 | }; |
316 | |
317 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]} |
ce556881 |
318 | if $is_new_res; |
319 | } |
320 | splice @{$_[0]}, $result_pos; |
321 | ', |
52864fbd |
322 | 'Same 1:1 descending terminating with chained 1:M:M but with collapse, HRI-direct', |
ce556881 |
323 | ); |
324 | |
4e9fc3f3 |
325 | $infmap = [qw/ |
3d8caf63 |
326 | tracks.lyrics.existing_lyric_versions.text |
4e9fc3f3 |
327 | existing_single_track.cd.artist.artistid |
328 | existing_single_track.cd.artist.cds.year |
329 | year |
330 | genreid |
331 | tracks.title |
332 | existing_single_track.cd.artist.cds.cdid |
333 | latest_cd |
334 | existing_single_track.cd.artist.cds.tracks.title |
335 | existing_single_track.cd.artist.cds.genreid |
3d8caf63 |
336 | tracks.lyrics.existing_lyric_versions.lyric_id |
4e9fc3f3 |
337 | /]; |
338 | |
339 | is_deeply ( |
82f0e0aa |
340 | $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }), |
4e9fc3f3 |
341 | { |
9f98c4b2 |
342 | -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid |
4e9fc3f3 |
343 | |
344 | existing_single_track => { |
9f98c4b2 |
345 | -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid |
4e9fc3f3 |
346 | -is_single => 1, |
347 | |
348 | cd => { |
9f98c4b2 |
349 | -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid |
4e9fc3f3 |
350 | -is_single => 1, |
351 | |
352 | artist => { |
9f98c4b2 |
353 | -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid |
4e9fc3f3 |
354 | -is_single => 1, |
355 | |
356 | cds => { |
9f98c4b2 |
357 | -identifying_columns => [ 1, 6 ], # existing_single_track.cd.artist.cds.cdid |
4e9fc3f3 |
358 | -is_optional => 1, |
359 | |
360 | tracks => { |
9f98c4b2 |
361 | -identifying_columns => [ 1, 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title |
4e9fc3f3 |
362 | -is_optional => 1, |
363 | } |
364 | } |
365 | } |
366 | } |
367 | }, |
368 | tracks => { |
9f98c4b2 |
369 | -identifying_columns => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title |
4e9fc3f3 |
370 | -is_optional => 1, |
371 | |
372 | lyrics => { |
3d8caf63 |
373 | -identifying_columns => [ 1, 5, 10 ], # existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id |
4e9fc3f3 |
374 | -is_single => 1, |
375 | -is_optional => 1, |
376 | |
3d8caf63 |
377 | existing_lyric_versions => { |
378 | -identifying_columns => [ 0, 1, 5, 10 ], # tracks.lyrics.existing_lyric_versions.text, existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id |
4e9fc3f3 |
379 | }, |
380 | }, |
381 | } |
382 | }, |
383 | 'Correct collapse map constructed', |
384 | ); |
385 | |
386 | is_same_src ( |
387 | $schema->source ('CD')->_mk_row_parser({ |
388 | inflate_map => $infmap, |
389 | collapse => 1, |
390 | }), |
9f98c4b2 |
391 | ' my ($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0,0); |
4e9fc3f3 |
392 | |
9f98c4b2 |
393 | while ($cur_row_data = ( |
4e9fc3f3 |
394 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
395 | || |
396 | ( $_[1] and $_[1]->() ) |
397 | ) { |
398 | |
9f98c4b2 |
399 | $cur_row_ids{$_} = defined $cur_row_data->[$_] ? $cur_row_data->[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
3d8caf63 |
400 | for (0, 1, 5, 6, 8, 10); |
4e9fc3f3 |
401 | |
9f98c4b2 |
402 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
403 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
404 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{1}} ); |
4e9fc3f3 |
405 | |
9f98c4b2 |
406 | $collapse_idx[0]{$cur_row_ids{1}} ||= [{ genreid => $cur_row_data->[4], latest_cd => $cur_row_data->[7], year => $cur_row_data->[3] }]; |
4e9fc3f3 |
407 | |
52864fbd |
408 | $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} ||= $collapse_idx[1]{$cur_row_ids{1}} ||= []; |
409 | $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}} ||= []; |
9f98c4b2 |
410 | $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}} ||= [{ artistid => $cur_row_data->[1] }]; |
4e9fc3f3 |
411 | |
ce556881 |
412 | (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} ) |
413 | and |
414 | push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, ( |
415 | $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} = [{ cdid => $cur_row_data->[6], genreid => $cur_row_data->[9], year => $cur_row_data->[2] }] |
416 | ); |
52864fbd |
417 | defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ ); |
4e9fc3f3 |
418 | |
ce556881 |
419 | (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} ) |
420 | and |
421 | push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, ( |
422 | $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }] |
423 | ); |
52864fbd |
424 | defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ ); |
4e9fc3f3 |
425 | |
ce556881 |
426 | (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} ) |
427 | and |
428 | push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, ( |
429 | $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }] |
430 | ); |
52864fbd |
431 | defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ ); |
4e9fc3f3 |
432 | |
52864fbd |
433 | $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics} ||= $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} ||= []; |
434 | defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ ); |
4e9fc3f3 |
435 | |
ce556881 |
436 | (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} ) |
437 | and |
438 | push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, ( |
439 | $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} = [{ lyric_id => $cur_row_data->[10], text => $cur_row_data->[0] }] |
440 | ); |
4e9fc3f3 |
441 | |
9f98c4b2 |
442 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{1}} |
4e9fc3f3 |
443 | if $is_new_res; |
444 | } |
445 | |
446 | splice @{$_[0]}, $result_pos; |
447 | ', |
448 | 'Multiple has_many on multiple branches torture test', |
449 | ); |
450 | |
ce556881 |
451 | is_same_src ( |
452 | $schema->source ('CD')->_mk_row_parser({ |
453 | inflate_map => $infmap, |
454 | collapse => 1, |
ce556881 |
455 | }), |
456 | ' my ($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0,0); |
457 | |
458 | while ($cur_row_data = ( |
459 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
460 | || |
461 | ( $_[1] and $_[1]->() ) |
462 | ) { |
463 | |
464 | $cur_row_ids{$_} = defined $cur_row_data->[$_] ? $cur_row_data->[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
465 | for (0, 1, 5, 6, 8, 10); |
466 | |
467 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
468 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
469 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{1}} ); |
470 | |
471 | $collapse_idx[0]{$cur_row_ids{1}} ||= [{ genreid => $cur_row_data->[4], latest_cd => $cur_row_data->[7], year => $cur_row_data->[3] }]; |
472 | |
52864fbd |
473 | $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} ||= $collapse_idx[1]{$cur_row_ids{1}} ||= []; |
474 | $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}} ||= []; |
ce556881 |
475 | $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}} ||= [{ artistid => $cur_row_data->[1] }]; |
476 | |
ce556881 |
477 | (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} ) |
478 | and |
479 | push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, ( |
480 | $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} = [{ cdid => $cur_row_data->[6], genreid => $cur_row_data->[9], year => $cur_row_data->[2] }] |
481 | ); |
52864fbd |
482 | defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ ); |
ce556881 |
483 | |
ce556881 |
484 | (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} ) |
485 | and |
486 | push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, ( |
487 | $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }] |
488 | ); |
52864fbd |
489 | defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ ); |
ce556881 |
490 | |
ce556881 |
491 | (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} ) |
492 | and |
493 | push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, ( |
494 | $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }] |
495 | ); |
52864fbd |
496 | defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ ); |
ce556881 |
497 | |
52864fbd |
498 | $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics} ||= $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} ||= []; |
499 | defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ ); |
ce556881 |
500 | |
ce556881 |
501 | (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} ) |
502 | and |
503 | push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, ( |
504 | $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} = [{ lyric_id => $cur_row_data->[10], text => $cur_row_data->[0] }] |
505 | ); |
ce556881 |
506 | |
507 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{1}} |
508 | if $is_new_res; |
509 | } |
510 | |
511 | splice @{$_[0]}, $result_pos; |
512 | ', |
52864fbd |
513 | 'Multiple has_many on multiple branches with branch torture test', |
ce556881 |
514 | ); |
515 | |
fcf32d04 |
516 | $infmap = [ |
517 | 'single_track.trackid', # (0) definitive link to root from 1:1:1:1:M:M chain |
518 | 'year', # (1) non-unique |
519 | 'tracks.cd', # (2) \ together both uniqueness for second multirel |
520 | 'tracks.title', # (3) / and definitive link back to root |
521 | 'single_track.cd.artist.cds.cdid', # (4) to give uniquiness to ...tracks.title below |
522 | 'single_track.cd.artist.cds.year', # (5) non-unique |
523 | 'single_track.cd.artist.artistid', # (6) uniqufies entire parental chain |
524 | 'single_track.cd.artist.cds.genreid', # (7) nullable |
525 | 'single_track.cd.artist.cds.tracks.title',# (8) unique when combined with ...cds.cdid above |
526 | ]; |
527 | |
528 | is_deeply ( |
529 | $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }), |
530 | { |
9f98c4b2 |
531 | -identifying_columns => [], |
532 | -identifying_columns_variants => [ |
fcf32d04 |
533 | [ 0 ], [ 2 ], |
534 | ], |
535 | single_track => { |
9f98c4b2 |
536 | -identifying_columns => [ 0 ], |
fcf32d04 |
537 | -is_optional => 1, |
538 | -is_single => 1, |
fcf32d04 |
539 | cd => { |
9f98c4b2 |
540 | -identifying_columns => [ 0 ], |
fcf32d04 |
541 | -is_single => 1, |
fcf32d04 |
542 | artist => { |
9f98c4b2 |
543 | -identifying_columns => [ 0 ], |
fcf32d04 |
544 | -is_single => 1, |
fcf32d04 |
545 | cds => { |
9f98c4b2 |
546 | -identifying_columns => [ 0, 4 ], |
fcf32d04 |
547 | -is_optional => 1, |
fcf32d04 |
548 | tracks => { |
9f98c4b2 |
549 | -identifying_columns => [ 0, 4, 8 ], |
fcf32d04 |
550 | -is_optional => 1, |
fcf32d04 |
551 | } |
552 | } |
553 | } |
554 | } |
555 | }, |
556 | tracks => { |
9f98c4b2 |
557 | -identifying_columns => [ 2, 3 ], |
fcf32d04 |
558 | -is_optional => 1, |
fcf32d04 |
559 | } |
560 | }, |
561 | 'Correct underdefined root collapse map constructed' |
562 | ); |
563 | |
564 | is_same_src ( |
565 | $schema->source ('CD')->_mk_row_parser({ |
566 | inflate_map => $infmap, |
567 | collapse => 1, |
568 | }), |
9f98c4b2 |
569 | ' my($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0, 0); |
fcf32d04 |
570 | |
9f98c4b2 |
571 | while ($cur_row_data = ( |
fcf32d04 |
572 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
573 | || |
574 | ( $_[1] and $_[1]->() ) |
575 | ) { |
576 | |
9f98c4b2 |
577 | $cur_row_ids{$_} = defined $$cur_row_data[$_] ? $$cur_row_data[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
fcf32d04 |
578 | for (0, 2, 3, 4, 8); |
579 | |
580 | # cache expensive set of ops in a non-existent rowid slot |
9f98c4b2 |
581 | $cur_row_ids{10} = ( |
582 | ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} )) |
fcf32d04 |
583 | or |
9f98c4b2 |
584 | ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} )) |
fcf32d04 |
585 | or |
586 | "\0$rows_pos\0" |
587 | ); |
588 | |
9f98c4b2 |
589 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
590 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
591 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{10}} ); |
fcf32d04 |
592 | |
9f98c4b2 |
593 | $collapse_idx[0]{$cur_row_ids{10}} ||= [{ year => $$cur_row_data[1] }]; |
fcf32d04 |
594 | |
52864fbd |
595 | $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track} ||= ($collapse_idx[1]{$cur_row_ids{0}} ||= [{ trackid => $cur_row_data->[0] }]); |
596 | defined($cur_row_data->[0]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track}, __NBC__ ); |
fcf32d04 |
597 | |
52864fbd |
598 | $collapse_idx[1]{$cur_row_ids{0}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{0}} ||= []; |
fcf32d04 |
599 | |
52864fbd |
600 | $collapse_idx[2]{$cur_row_ids{0}}[1]{artist} ||= ($collapse_idx[3]{$cur_row_ids{0}} ||= [{ artistid => $cur_row_data->[6] }]); |
fcf32d04 |
601 | |
ce556881 |
602 | (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} ) |
603 | and |
604 | push @{$collapse_idx[3]{$cur_row_ids{0}}[1]{cds}}, ( |
52864fbd |
605 | $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} = [{ cdid => $cur_row_data->[4], genreid => $cur_row_data->[7], year => $cur_row_data->[5] }] |
ce556881 |
606 | ); |
52864fbd |
607 | defined($cur_row_data->[4]) or bless ( $collapse_idx[3]{$cur_row_ids{0}}[1]{cds}, __NBC__ ); |
fcf32d04 |
608 | |
ce556881 |
609 | (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} ) |
610 | and |
611 | push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}}, ( |
52864fbd |
612 | $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }] |
ce556881 |
613 | ); |
52864fbd |
614 | defined($cur_row_data->[8]) or bless ( $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}, __NBC__ ); |
fcf32d04 |
615 | |
ce556881 |
616 | (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} ) |
617 | and |
618 | push @{$collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}}, ( |
52864fbd |
619 | $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = [{ cd => $$cur_row_data[2], title => $cur_row_data->[3] }] |
ce556881 |
620 | ); |
52864fbd |
621 | defined($cur_row_data->[2]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}, __NBC__ ); |
fcf32d04 |
622 | |
9f98c4b2 |
623 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{10}} |
fcf32d04 |
624 | if $is_new_res; |
625 | } |
626 | |
627 | splice @{$_[0]}, $result_pos; |
628 | ', |
629 | 'Multiple has_many on multiple branches with underdefined root torture test', |
630 | ); |
631 | |
ce556881 |
632 | is_same_src ( |
633 | $schema->source ('CD')->_mk_row_parser({ |
634 | inflate_map => $infmap, |
635 | collapse => 1, |
ce556881 |
636 | hri_style => 1, |
637 | }), |
7596ddca |
638 | ' my($rows_pos, $result_pos, $cur_row_data, @collapse_idx, $is_new_res) = (0, 0); |
ce556881 |
639 | |
640 | while ($cur_row_data = ( |
641 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
642 | || |
643 | ( $_[1] and $_[1]->() ) |
644 | ) { |
645 | |
ce556881 |
646 | # cache expensive set of ops in a non-existent rowid slot |
7596ddca |
647 | $cur_row_data->[10] = ( |
ce556881 |
648 | ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} )) |
649 | or |
650 | ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} )) |
651 | or |
652 | "\0$rows_pos\0" |
653 | ); |
654 | |
655 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
656 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
7596ddca |
657 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_data->[10]} ); |
ce556881 |
658 | |
7596ddca |
659 | $collapse_idx[0]{$cur_row_data->[10]} ||= { year => $$cur_row_data[1] }; |
ce556881 |
660 | |
7596ddca |
661 | (! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_data->[10]}{single_track} = undef : do { |
ce556881 |
662 | |
7596ddca |
663 | $collapse_idx[0]{$cur_row_data->[10]}{single_track} ||= ($collapse_idx[1]{$cur_row_data->[0]} ||= { trackid => $$cur_row_data[0] }); |
ce556881 |
664 | |
7596ddca |
665 | $collapse_idx[1]{$cur_row_data->[0]}{cd} ||= $collapse_idx[2]{$cur_row_data->[0]}; |
ce556881 |
666 | |
7596ddca |
667 | $collapse_idx[2]{$cur_row_data->[0]}{artist} ||= ($collapse_idx[3]{$cur_row_data->[0]} ||= { artistid => $$cur_row_data[6] }); |
ce556881 |
668 | |
7596ddca |
669 | (! defined $cur_row_data->[4] ) ? $collapse_idx[3]{$cur_row_data->[0]}{cds} = [] : do { |
ce556881 |
670 | |
7596ddca |
671 | (! $collapse_idx[4]{$cur_row_data->[0]}{$cur_row_data->[4]} ) |
672 | and |
673 | push @{$collapse_idx[3]{$cur_row_data->[0]}{cds}}, ( |
674 | $collapse_idx[4]{$cur_row_data->[0]}{$cur_row_data->[4]} = { cdid => $$cur_row_data[4], genreid => $$cur_row_data[7], year => $$cur_row_data[5] } |
675 | ); |
ce556881 |
676 | |
7596ddca |
677 | (! defined $cur_row_data->[8] ) ? $collapse_idx[4]{$cur_row_data->[0]}{$cur_row_data->[4]}{tracks} = [] : do { |
678 | |
679 | (! $collapse_idx[5]{$cur_row_data->[0]}{$cur_row_data->[4]}{$cur_row_data->[8]} ) |
680 | and |
681 | push @{$collapse_idx[4]{$cur_row_data->[0]}{$cur_row_data->[4]}{tracks}}, ( |
682 | $collapse_idx[5]{$cur_row_data->[0]}{$cur_row_data->[4]}{$cur_row_data->[8]} = { title => $$cur_row_data[8] } |
683 | ); |
684 | }; |
685 | }; |
686 | }; |
687 | |
688 | (! defined $cur_row_data->[2] ) ? $collapse_idx[0]{$cur_row_data->[10]}{tracks} = [] : do { |
689 | (! $collapse_idx[6]{$cur_row_data->[2]}{$cur_row_data->[3]} ) |
690 | and |
691 | push @{$collapse_idx[0]{$cur_row_data->[10]}{tracks}}, ( |
692 | $collapse_idx[6]{$cur_row_data->[2]}{$cur_row_data->[3]} = { cd => $$cur_row_data[2], title => $$cur_row_data[3] } |
693 | ); |
694 | }; |
695 | |
696 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_data->[10]} |
ce556881 |
697 | if $is_new_res; |
698 | } |
699 | |
700 | splice @{$_[0]}, $result_pos; |
701 | ', |
52864fbd |
702 | 'Multiple has_many on multiple branches with underdefined root, HRI-direct torture test', |
ce556881 |
703 | ); |
704 | |
4e9fc3f3 |
705 | done_testing; |
706 | |
707 | my $deparser; |
708 | sub is_same_src { |
709 | $deparser ||= B::Deparse->new; |
710 | local $Test::Builder::Level = $Test::Builder::Level + 1; |
711 | |
52864fbd |
712 | my ($got, $expect) = @_; |
713 | |
714 | $expect =~ s/__NBC__/B::perlstring($DBIx::Class::ResultSource::RowParser::Util::null_branch_class)/ge; |
715 | |
bdbd2ae8 |
716 | $expect = " { use strict; use warnings FATAL => 'all';\n$expect\n }"; |
717 | |
52864fbd |
718 | my @normalized = map { |
4e9fc3f3 |
719 | my $cref = eval "sub { $_ }" or do { |
720 | fail "Coderef does not compile!\n\n$@\n\n$_"; |
721 | return undef; |
722 | }; |
723 | $deparser->coderef2text($cref); |
52864fbd |
724 | } ($got, $expect); |
725 | |
726 | &is (@normalized, $_[2]||() ) or do { |
727 | eval { require Test::Differences } |
728 | ? &Test::Differences::eq_or_diff( @normalized, $_[2]||() ) |
729 | : note ("Original sources:\n\n$got\n\n$expect\n"); |
730 | BAIL_OUT(''); |
731 | }; |
4e9fc3f3 |
732 | } |