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