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 | }), |
271 | ' my($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0, 0); |
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 | |
279 | $cur_row_ids{$_} = defined $cur_row_data->[$_] ? $cur_row_data->[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
280 | for (0, 1, 3, 4, 5); |
281 | |
282 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
283 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
284 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} ); |
285 | |
286 | # the rowdata itself for root node |
287 | $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] }; |
288 | |
289 | # prefetch data of single_track (placed in root) |
290 | $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}{single_track} ||= $collapse_idx[1]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} |
291 | if defined $cur_row_data->[1]; |
292 | $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}{single_track} ||= undef; |
293 | |
294 | # prefetch data of cd (placed in single_track) |
295 | $collapse_idx[1]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cd} ||= $collapse_idx[2]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}; |
296 | |
297 | # prefetch data of artist ( placed in single_track->cd) |
298 | $collapse_idx[2]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{artist} ||= $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}} ||= { artistid => $cur_row_data->[1] }; |
299 | |
300 | # prefetch data of cds (if available) |
301 | ( defined $cur_row_data->[3] ) |
302 | and |
303 | (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} ) |
304 | and |
305 | push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cds}}, ( |
306 | $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = { cdid => $cur_row_data->[3] } |
307 | ); |
308 | $collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}{cds} ||= []; |
309 | |
310 | # prefetch data of tracks (if available) |
311 | ( defined $cur_row_data->[0] ) |
312 | and |
313 | (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} ) |
314 | and |
315 | push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}{tracks}}, ( |
316 | $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] } |
317 | ); |
318 | $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}{tracks} ||= []; |
319 | |
320 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}} |
321 | if $is_new_res; |
322 | } |
323 | splice @{$_[0]}, $result_pos; |
324 | ', |
52864fbd |
325 | 'Same 1:1 descending terminating with chained 1:M:M but with collapse, HRI-direct', |
ce556881 |
326 | ); |
327 | |
4e9fc3f3 |
328 | $infmap = [qw/ |
3d8caf63 |
329 | tracks.lyrics.existing_lyric_versions.text |
4e9fc3f3 |
330 | existing_single_track.cd.artist.artistid |
331 | existing_single_track.cd.artist.cds.year |
332 | year |
333 | genreid |
334 | tracks.title |
335 | existing_single_track.cd.artist.cds.cdid |
336 | latest_cd |
337 | existing_single_track.cd.artist.cds.tracks.title |
338 | existing_single_track.cd.artist.cds.genreid |
3d8caf63 |
339 | tracks.lyrics.existing_lyric_versions.lyric_id |
4e9fc3f3 |
340 | /]; |
341 | |
342 | is_deeply ( |
82f0e0aa |
343 | $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }), |
4e9fc3f3 |
344 | { |
9f98c4b2 |
345 | -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid |
4e9fc3f3 |
346 | |
347 | existing_single_track => { |
9f98c4b2 |
348 | -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid |
4e9fc3f3 |
349 | -is_single => 1, |
350 | |
351 | cd => { |
9f98c4b2 |
352 | -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid |
4e9fc3f3 |
353 | -is_single => 1, |
354 | |
355 | artist => { |
9f98c4b2 |
356 | -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid |
4e9fc3f3 |
357 | -is_single => 1, |
358 | |
359 | cds => { |
9f98c4b2 |
360 | -identifying_columns => [ 1, 6 ], # existing_single_track.cd.artist.cds.cdid |
4e9fc3f3 |
361 | -is_optional => 1, |
362 | |
363 | tracks => { |
9f98c4b2 |
364 | -identifying_columns => [ 1, 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title |
4e9fc3f3 |
365 | -is_optional => 1, |
366 | } |
367 | } |
368 | } |
369 | } |
370 | }, |
371 | tracks => { |
9f98c4b2 |
372 | -identifying_columns => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title |
4e9fc3f3 |
373 | -is_optional => 1, |
374 | |
375 | lyrics => { |
3d8caf63 |
376 | -identifying_columns => [ 1, 5, 10 ], # existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id |
4e9fc3f3 |
377 | -is_single => 1, |
378 | -is_optional => 1, |
379 | |
3d8caf63 |
380 | existing_lyric_versions => { |
381 | -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 |
382 | }, |
383 | }, |
384 | } |
385 | }, |
386 | 'Correct collapse map constructed', |
387 | ); |
388 | |
389 | is_same_src ( |
390 | $schema->source ('CD')->_mk_row_parser({ |
391 | inflate_map => $infmap, |
392 | collapse => 1, |
393 | }), |
9f98c4b2 |
394 | ' my ($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0,0); |
4e9fc3f3 |
395 | |
9f98c4b2 |
396 | while ($cur_row_data = ( |
4e9fc3f3 |
397 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
398 | || |
399 | ( $_[1] and $_[1]->() ) |
400 | ) { |
401 | |
9f98c4b2 |
402 | $cur_row_ids{$_} = defined $cur_row_data->[$_] ? $cur_row_data->[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
3d8caf63 |
403 | for (0, 1, 5, 6, 8, 10); |
4e9fc3f3 |
404 | |
9f98c4b2 |
405 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
406 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
407 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{1}} ); |
4e9fc3f3 |
408 | |
9f98c4b2 |
409 | $collapse_idx[0]{$cur_row_ids{1}} ||= [{ genreid => $cur_row_data->[4], latest_cd => $cur_row_data->[7], year => $cur_row_data->[3] }]; |
4e9fc3f3 |
410 | |
52864fbd |
411 | $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} ||= $collapse_idx[1]{$cur_row_ids{1}} ||= []; |
412 | $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}} ||= []; |
9f98c4b2 |
413 | $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}} ||= [{ artistid => $cur_row_data->[1] }]; |
4e9fc3f3 |
414 | |
ce556881 |
415 | (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} ) |
416 | and |
417 | push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, ( |
418 | $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] }] |
419 | ); |
52864fbd |
420 | defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ ); |
4e9fc3f3 |
421 | |
ce556881 |
422 | (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} ) |
423 | and |
424 | push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, ( |
425 | $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }] |
426 | ); |
52864fbd |
427 | defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ ); |
4e9fc3f3 |
428 | |
ce556881 |
429 | (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} ) |
430 | and |
431 | push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, ( |
432 | $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }] |
433 | ); |
52864fbd |
434 | defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ ); |
4e9fc3f3 |
435 | |
52864fbd |
436 | $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}} ||= []; |
437 | defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ ); |
4e9fc3f3 |
438 | |
ce556881 |
439 | (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} ) |
440 | and |
441 | push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, ( |
442 | $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] }] |
443 | ); |
4e9fc3f3 |
444 | |
9f98c4b2 |
445 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{1}} |
4e9fc3f3 |
446 | if $is_new_res; |
447 | } |
448 | |
449 | splice @{$_[0]}, $result_pos; |
450 | ', |
451 | 'Multiple has_many on multiple branches torture test', |
452 | ); |
453 | |
ce556881 |
454 | is_same_src ( |
455 | $schema->source ('CD')->_mk_row_parser({ |
456 | inflate_map => $infmap, |
457 | collapse => 1, |
ce556881 |
458 | }), |
459 | ' my ($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0,0); |
460 | |
461 | while ($cur_row_data = ( |
462 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
463 | || |
464 | ( $_[1] and $_[1]->() ) |
465 | ) { |
466 | |
467 | $cur_row_ids{$_} = defined $cur_row_data->[$_] ? $cur_row_data->[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
468 | for (0, 1, 5, 6, 8, 10); |
469 | |
470 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
471 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
472 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{1}} ); |
473 | |
474 | $collapse_idx[0]{$cur_row_ids{1}} ||= [{ genreid => $cur_row_data->[4], latest_cd => $cur_row_data->[7], year => $cur_row_data->[3] }]; |
475 | |
52864fbd |
476 | $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} ||= $collapse_idx[1]{$cur_row_ids{1}} ||= []; |
477 | $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{1}} ||= []; |
ce556881 |
478 | $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} ||= $collapse_idx[3]{$cur_row_ids{1}} ||= [{ artistid => $cur_row_data->[1] }]; |
479 | |
ce556881 |
480 | (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} ) |
481 | and |
482 | push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, ( |
483 | $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] }] |
484 | ); |
52864fbd |
485 | defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ ); |
ce556881 |
486 | |
ce556881 |
487 | (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} ) |
488 | and |
489 | push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, ( |
490 | $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }] |
491 | ); |
52864fbd |
492 | defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ ); |
ce556881 |
493 | |
ce556881 |
494 | (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} ) |
495 | and |
496 | push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, ( |
497 | $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }] |
498 | ); |
52864fbd |
499 | defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ ); |
ce556881 |
500 | |
52864fbd |
501 | $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}} ||= []; |
502 | defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ ); |
ce556881 |
503 | |
ce556881 |
504 | (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} ) |
505 | and |
506 | push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, ( |
507 | $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] }] |
508 | ); |
ce556881 |
509 | |
510 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{1}} |
511 | if $is_new_res; |
512 | } |
513 | |
514 | splice @{$_[0]}, $result_pos; |
515 | ', |
52864fbd |
516 | 'Multiple has_many on multiple branches with branch torture test', |
ce556881 |
517 | ); |
518 | |
fcf32d04 |
519 | $infmap = [ |
520 | 'single_track.trackid', # (0) definitive link to root from 1:1:1:1:M:M chain |
521 | 'year', # (1) non-unique |
522 | 'tracks.cd', # (2) \ together both uniqueness for second multirel |
523 | 'tracks.title', # (3) / and definitive link back to root |
524 | 'single_track.cd.artist.cds.cdid', # (4) to give uniquiness to ...tracks.title below |
525 | 'single_track.cd.artist.cds.year', # (5) non-unique |
526 | 'single_track.cd.artist.artistid', # (6) uniqufies entire parental chain |
527 | 'single_track.cd.artist.cds.genreid', # (7) nullable |
528 | 'single_track.cd.artist.cds.tracks.title',# (8) unique when combined with ...cds.cdid above |
529 | ]; |
530 | |
531 | is_deeply ( |
532 | $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }), |
533 | { |
9f98c4b2 |
534 | -identifying_columns => [], |
535 | -identifying_columns_variants => [ |
fcf32d04 |
536 | [ 0 ], [ 2 ], |
537 | ], |
538 | single_track => { |
9f98c4b2 |
539 | -identifying_columns => [ 0 ], |
fcf32d04 |
540 | -is_optional => 1, |
541 | -is_single => 1, |
fcf32d04 |
542 | cd => { |
9f98c4b2 |
543 | -identifying_columns => [ 0 ], |
fcf32d04 |
544 | -is_single => 1, |
fcf32d04 |
545 | artist => { |
9f98c4b2 |
546 | -identifying_columns => [ 0 ], |
fcf32d04 |
547 | -is_single => 1, |
fcf32d04 |
548 | cds => { |
9f98c4b2 |
549 | -identifying_columns => [ 0, 4 ], |
fcf32d04 |
550 | -is_optional => 1, |
fcf32d04 |
551 | tracks => { |
9f98c4b2 |
552 | -identifying_columns => [ 0, 4, 8 ], |
fcf32d04 |
553 | -is_optional => 1, |
fcf32d04 |
554 | } |
555 | } |
556 | } |
557 | } |
558 | }, |
559 | tracks => { |
9f98c4b2 |
560 | -identifying_columns => [ 2, 3 ], |
fcf32d04 |
561 | -is_optional => 1, |
fcf32d04 |
562 | } |
563 | }, |
564 | 'Correct underdefined root collapse map constructed' |
565 | ); |
566 | |
567 | is_same_src ( |
568 | $schema->source ('CD')->_mk_row_parser({ |
569 | inflate_map => $infmap, |
570 | collapse => 1, |
571 | }), |
9f98c4b2 |
572 | ' my($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0, 0); |
fcf32d04 |
573 | |
9f98c4b2 |
574 | while ($cur_row_data = ( |
fcf32d04 |
575 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
576 | || |
577 | ( $_[1] and $_[1]->() ) |
578 | ) { |
579 | |
9f98c4b2 |
580 | $cur_row_ids{$_} = defined $$cur_row_data[$_] ? $$cur_row_data[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
fcf32d04 |
581 | for (0, 2, 3, 4, 8); |
582 | |
583 | # cache expensive set of ops in a non-existent rowid slot |
9f98c4b2 |
584 | $cur_row_ids{10} = ( |
585 | ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} )) |
fcf32d04 |
586 | or |
9f98c4b2 |
587 | ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} )) |
fcf32d04 |
588 | or |
589 | "\0$rows_pos\0" |
590 | ); |
591 | |
9f98c4b2 |
592 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
593 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
594 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{10}} ); |
fcf32d04 |
595 | |
9f98c4b2 |
596 | $collapse_idx[0]{$cur_row_ids{10}} ||= [{ year => $$cur_row_data[1] }]; |
fcf32d04 |
597 | |
52864fbd |
598 | $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track} ||= ($collapse_idx[1]{$cur_row_ids{0}} ||= [{ trackid => $cur_row_data->[0] }]); |
599 | defined($cur_row_data->[0]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track}, __NBC__ ); |
fcf32d04 |
600 | |
52864fbd |
601 | $collapse_idx[1]{$cur_row_ids{0}}[1]{cd} ||= $collapse_idx[2]{$cur_row_ids{0}} ||= []; |
fcf32d04 |
602 | |
52864fbd |
603 | $collapse_idx[2]{$cur_row_ids{0}}[1]{artist} ||= ($collapse_idx[3]{$cur_row_ids{0}} ||= [{ artistid => $cur_row_data->[6] }]); |
fcf32d04 |
604 | |
ce556881 |
605 | (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} ) |
606 | and |
607 | push @{$collapse_idx[3]{$cur_row_ids{0}}[1]{cds}}, ( |
52864fbd |
608 | $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 |
609 | ); |
52864fbd |
610 | defined($cur_row_data->[4]) or bless ( $collapse_idx[3]{$cur_row_ids{0}}[1]{cds}, __NBC__ ); |
fcf32d04 |
611 | |
ce556881 |
612 | (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} ) |
613 | and |
614 | push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}}, ( |
52864fbd |
615 | $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }] |
ce556881 |
616 | ); |
52864fbd |
617 | defined($cur_row_data->[8]) or bless ( $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}, __NBC__ ); |
fcf32d04 |
618 | |
ce556881 |
619 | (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} ) |
620 | and |
621 | push @{$collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}}, ( |
52864fbd |
622 | $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = [{ cd => $$cur_row_data[2], title => $cur_row_data->[3] }] |
ce556881 |
623 | ); |
52864fbd |
624 | defined($cur_row_data->[2]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}, __NBC__ ); |
fcf32d04 |
625 | |
9f98c4b2 |
626 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{10}} |
fcf32d04 |
627 | if $is_new_res; |
628 | } |
629 | |
630 | splice @{$_[0]}, $result_pos; |
631 | ', |
632 | 'Multiple has_many on multiple branches with underdefined root torture test', |
633 | ); |
634 | |
ce556881 |
635 | is_same_src ( |
636 | $schema->source ('CD')->_mk_row_parser({ |
637 | inflate_map => $infmap, |
638 | collapse => 1, |
ce556881 |
639 | hri_style => 1, |
640 | }), |
641 | ' my($rows_pos, $result_pos, $cur_row_data, %cur_row_ids, @collapse_idx, $is_new_res) = (0, 0); |
642 | |
643 | while ($cur_row_data = ( |
644 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
645 | || |
646 | ( $_[1] and $_[1]->() ) |
647 | ) { |
648 | |
649 | $cur_row_ids{$_} = defined $$cur_row_data[$_] ? $$cur_row_data[$_] : "\0NULL\xFF$rows_pos\xFF$_\0" |
650 | for (0, 2, 3, 4, 8); |
651 | |
652 | # cache expensive set of ops in a non-existent rowid slot |
653 | $cur_row_ids{10} = ( |
654 | ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} )) |
655 | or |
656 | ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} )) |
657 | or |
658 | "\0$rows_pos\0" |
659 | ); |
660 | |
661 | # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2] |
662 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row_data) and last |
663 | if ( $is_new_res = ! $collapse_idx[0]{$cur_row_ids{10}} ); |
664 | |
665 | $collapse_idx[0]{$cur_row_ids{10}} ||= { year => $$cur_row_data[1] }; |
666 | |
667 | (defined $cur_row_data->[0]) |
668 | and |
669 | $collapse_idx[0]{$cur_row_ids{10}}{single_track} ||= ($collapse_idx[1]{$cur_row_ids{0}} ||= { trackid => $$cur_row_data[0] }); |
670 | $collapse_idx[0]{$cur_row_ids{10}}{single_track} ||= undef; |
671 | |
672 | $collapse_idx[1]{$cur_row_ids{0}}{cd} ||= $collapse_idx[2]{$cur_row_ids{0}}; |
673 | |
674 | $collapse_idx[2]{$cur_row_ids{0}}{artist} ||= ($collapse_idx[3]{$cur_row_ids{0}} ||= { artistid => $$cur_row_data[6] }); |
675 | |
676 | (defined $cur_row_data->[4]) |
677 | and |
678 | (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} ) |
679 | and |
680 | push @{$collapse_idx[3]{$cur_row_ids{0}}{cds}}, ( |
681 | $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] } |
682 | ); |
683 | $collapse_idx[3]{$cur_row_ids{0}}{cds} ||= []; |
684 | |
685 | (defined $cur_row_data->[8]) |
686 | and |
687 | (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} ) |
688 | and |
689 | push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks}}, ( |
690 | $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = { title => $$cur_row_data[8] } |
691 | ); |
692 | $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks} ||= []; |
693 | |
694 | (defined $cur_row_data->[2]) |
695 | and |
696 | (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} ) |
697 | and |
698 | push @{$collapse_idx[0]{$cur_row_ids{10}}{tracks}}, ( |
699 | $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = { cd => $$cur_row_data[2], title => $$cur_row_data[3] } |
700 | ); |
701 | $collapse_idx[0]{$cur_row_ids{10}}{tracks} ||= []; |
702 | |
703 | $_[0][$result_pos++] = $collapse_idx[0]{$cur_row_ids{10}} |
704 | if $is_new_res; |
705 | } |
706 | |
707 | splice @{$_[0]}, $result_pos; |
708 | ', |
52864fbd |
709 | 'Multiple has_many on multiple branches with underdefined root, HRI-direct torture test', |
ce556881 |
710 | ); |
711 | |
4e9fc3f3 |
712 | done_testing; |
713 | |
714 | my $deparser; |
715 | sub is_same_src { |
716 | $deparser ||= B::Deparse->new; |
717 | local $Test::Builder::Level = $Test::Builder::Level + 1; |
718 | |
52864fbd |
719 | my ($got, $expect) = @_; |
720 | |
721 | $expect =~ s/__NBC__/B::perlstring($DBIx::Class::ResultSource::RowParser::Util::null_branch_class)/ge; |
722 | |
723 | my @normalized = map { |
4e9fc3f3 |
724 | my $cref = eval "sub { $_ }" or do { |
725 | fail "Coderef does not compile!\n\n$@\n\n$_"; |
726 | return undef; |
727 | }; |
728 | $deparser->coderef2text($cref); |
52864fbd |
729 | } ($got, $expect); |
730 | |
731 | &is (@normalized, $_[2]||() ) or do { |
732 | eval { require Test::Differences } |
733 | ? &Test::Differences::eq_or_diff( @normalized, $_[2]||() ) |
734 | : note ("Original sources:\n\n$got\n\n$expect\n"); |
735 | BAIL_OUT(''); |
736 | }; |
4e9fc3f3 |
737 | } |