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 | |
9 | my $schema = DBICTest->init_schema(no_deploy => 1); |
10 | my $infmap = [qw/single_track.cd.artist.name year/]; |
11 | |
12 | is_same_src ( |
13 | $schema->source ('CD')->_mk_row_parser({ |
14 | inflate_map => $infmap, |
15 | }), |
16 | '$_ = [ |
17 | { year => $_->[1] }, |
18 | { single_track => [ |
19 | undef, |
20 | { cd => [ |
21 | undef, |
22 | { artist => [ |
23 | { name => $_->[0] }, |
24 | ] }, |
25 | ]}, |
26 | ]}, |
27 | ] for @{$_[0]}', |
28 | 'Simple 1:1 descending non-collapsing parser', |
29 | ); |
30 | |
31 | $infmap = [qw/ |
32 | single_track.cd.artist.artistid |
33 | year |
34 | single_track.cd.artist.cds.tracks.title |
35 | single_track.cd.artist.cds.cdid |
36 | title |
37 | artist |
38 | /]; |
39 | is_same_src ( |
40 | $schema->source ('CD')->_mk_row_parser({ |
41 | inflate_map => $infmap, |
42 | }), |
43 | '$_ = [ |
44 | { artist => $_->[5], title => $_->[4], year => $_->[1] }, |
45 | { single_track => [ |
46 | undef, |
47 | { cd => [ |
48 | undef, |
49 | { artist => [ |
50 | { artistid => $_->[0] }, |
51 | { cds => [ |
52 | { cdid => $_->[3] }, |
53 | { tracks => [ |
54 | { title => $_->[2] } |
55 | ] }, |
56 | ] }, |
57 | ] }, |
58 | ] }, |
59 | ] }, |
60 | ] for @{$_[0]}', |
61 | '1:1 descending non-collapsing parser terminating with chained 1:M:M', |
62 | ); |
63 | |
64 | is_deeply ( |
65 | $schema->source('CD')->_resolve_collapse({map { $infmap->[$_] => $_ } 0 .. $#$infmap}), |
66 | { |
67 | -node_index => 1, |
68 | -node_id => [ 4, 5 ], |
69 | -branch_id => [ 0, 2, 3, 4, 5 ], |
70 | |
71 | single_track => { |
72 | -node_index => 2, |
73 | -node_id => [ 4, 5], |
74 | -branch_id => [ 0, 2, 3, 4, 5], |
75 | -is_optional => 1, |
76 | -is_single => 1, |
77 | |
78 | cd => { |
79 | -node_index => 3, |
80 | -node_id => [ 4, 5 ], |
81 | -branch_id => [ 0, 2, 3, 4, 5 ], |
82 | -is_single => 1, |
83 | |
84 | artist => { |
85 | -node_index => 4, |
86 | -node_id => [ 0 ], |
87 | -branch_id => [ 0, 2, 3 ], |
88 | -is_single => 1, |
89 | |
90 | cds => { |
91 | -node_index => 5, |
92 | -node_id => [ 3 ], |
93 | -branch_id => [ 2, 3 ], |
94 | -is_optional => 1, |
95 | |
96 | tracks => { |
97 | -node_index => 6, |
98 | -node_id => [ 2, 3 ], |
99 | -branch_id => [ 2, 3 ], |
100 | -is_optional => 1, |
101 | }, |
102 | }, |
103 | }, |
104 | }, |
105 | }, |
106 | }, |
107 | 'Correct collapse map for 1:1 descending chain terminating with chained 1:M:M' |
108 | ); |
109 | |
110 | is_same_src ( |
111 | $schema->source ('CD')->_mk_row_parser({ |
112 | inflate_map => $infmap, |
113 | collapse => 1, |
114 | }), |
115 | ' my($rows_pos, $result_pos, $cur_row, @cur_row_ids, @collapse_idx, $is_new_res) = (0, 0); |
116 | |
117 | while ($cur_row = ( |
118 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
119 | || |
120 | ( $_[1] and $_[1]->() ) |
121 | ) { |
122 | |
123 | $cur_row_ids[$_] = defined $cur_row->[$_] ? $cur_row->[$_] : "\xFF\xFFN\xFFU\xFFL\xFFL\xFF\xFF" |
124 | for (0, 2, 3, 4, 5); |
125 | |
126 | # a present cref implies lazy prefetch, implies a supplied stash in $_[2] |
127 | $_[1] and $result_pos and unshift(@{$_[2]}, $cur_row) and last |
128 | if $is_new_res = ! $collapse_idx[1]{$cur_row_ids[4]}{$cur_row_ids[5]}; |
129 | |
130 | $collapse_idx[1]{$cur_row_ids[4]}{$cur_row_ids[5]} ||= [{ artist => $cur_row->[5], title => $cur_row->[4], year => $cur_row->[1] }]; |
131 | $collapse_idx[1]{$cur_row_ids[4]}{$cur_row_ids[5]}[1]{single_track} ||= $collapse_idx[2]{$cur_row_ids[4]}{$cur_row_ids[5]}; |
132 | $collapse_idx[2]{$cur_row_ids[4]}{$cur_row_ids[5]}[1]{cd} ||= $collapse_idx[3]{$cur_row_ids[4]}{$cur_row_ids[5]}; |
133 | $collapse_idx[3]{$cur_row_ids[4]}{$cur_row_ids[5]}[1]{artist} ||= $collapse_idx[4]{$cur_row_ids[0]} ||= [{ artistid => $cur_row->[0] }]; |
134 | |
135 | $collapse_idx[4]{$cur_row_ids[0]}[1]{cds} ||= []; |
136 | push @{$collapse_idx[4]{$cur_row_ids[0]}[1]{cds}}, $collapse_idx[5]{$cur_row_ids[3]} ||= [{ cdid => $cur_row->[3] }] |
137 | unless $collapse_idx[5]{$cur_row_ids[3]}; |
138 | |
139 | $collapse_idx[5]{$cur_row_ids[3]}[1]{tracks} ||= []; |
140 | push @{$collapse_idx[5]{$cur_row_ids[3]}[1]{tracks}}, $collapse_idx[6]{$cur_row_ids[2]}{$cur_row_ids[3]} ||= [{ title => $cur_row->[2] }] |
141 | unless $collapse_idx[6]{$cur_row_ids[2]}{$cur_row_ids[3]}; |
142 | |
143 | $_[0][$result_pos++] = $collapse_idx[1]{$cur_row_ids[4]}{$cur_row_ids[5]} |
144 | if $is_new_res; |
145 | } |
146 | splice @{$_[0]}, $result_pos; |
147 | ', |
148 | 'Same 1:1 descending terminating with chained 1:M:M but with collapse', |
149 | ); |
150 | |
151 | $infmap = [qw/ |
152 | tracks.lyrics.lyric_versions.text |
153 | existing_single_track.cd.artist.artistid |
154 | existing_single_track.cd.artist.cds.year |
155 | year |
156 | genreid |
157 | tracks.title |
158 | existing_single_track.cd.artist.cds.cdid |
159 | latest_cd |
160 | existing_single_track.cd.artist.cds.tracks.title |
161 | existing_single_track.cd.artist.cds.genreid |
162 | /]; |
163 | |
164 | is_deeply ( |
165 | $schema->source('CD')->_resolve_collapse({map { $infmap->[$_] => $_ } 0 .. $#$infmap}), |
166 | { |
167 | -node_index => 1, |
168 | -node_id => [ 1 ], # existing_single_track.cd.artist.artistid |
169 | -branch_id => [ 0, 1, 5, 6, 8 ], |
170 | |
171 | existing_single_track => { |
172 | -node_index => 2, |
173 | -node_id => [ 1 ], # existing_single_track.cd.artist.artistid |
174 | -branch_id => [ 1, 6, 8 ], |
175 | -is_single => 1, |
176 | |
177 | cd => { |
178 | -node_index => 3, |
179 | -node_id => [ 1 ], # existing_single_track.cd.artist.artistid |
180 | -branch_id => [ 1, 6, 8 ], |
181 | -is_single => 1, |
182 | |
183 | artist => { |
184 | -node_index => 4, |
185 | -node_id => [ 1 ], # existing_single_track.cd.artist.artistid |
186 | -branch_id => [ 1, 6, 8 ], |
187 | -is_single => 1, |
188 | |
189 | cds => { |
190 | -node_index => 5, |
191 | -node_id => [ 6 ], # existing_single_track.cd.artist.cds.cdid |
192 | -branch_id => [ 6, 8 ], |
193 | -is_optional => 1, |
194 | |
195 | tracks => { |
196 | -node_index => 6, |
197 | -node_id => [ 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title |
198 | -branch_id => [ 6, 8 ], |
199 | -is_optional => 1, |
200 | } |
201 | } |
202 | } |
203 | } |
204 | }, |
205 | tracks => { |
206 | -node_index => 7, |
207 | -node_id => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title |
208 | -branch_id => [ 0, 1, 5 ], |
209 | -is_optional => 1, |
210 | |
211 | lyrics => { |
212 | -node_index => 8, |
213 | -node_id => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title |
214 | -branch_id => [ 0, 1, 5 ], |
215 | -is_single => 1, |
216 | -is_optional => 1, |
217 | |
218 | lyric_versions => { |
219 | -node_index => 9, |
220 | -node_id => [ 0, 1, 5 ], # tracks.lyrics.lyric_versions.text, existing_single_track.cd.artist.artistid, tracks.title |
221 | -branch_id => [ 0, 1, 5 ], |
222 | -is_optional => 1, |
223 | }, |
224 | }, |
225 | } |
226 | }, |
227 | 'Correct collapse map constructed', |
228 | ); |
229 | |
230 | is_same_src ( |
231 | $schema->source ('CD')->_mk_row_parser({ |
232 | inflate_map => $infmap, |
233 | collapse => 1, |
234 | }), |
235 | ' my ($rows_pos, $result_pos, $cur_row, @cur_row_ids, @collapse_idx, $is_new_res) = (0,0); |
236 | |
237 | while ($cur_row = ( |
238 | ( $rows_pos >= 0 and $_[0][$rows_pos++] ) or do { $rows_pos = -1; undef } ) |
239 | || |
240 | ( $_[1] and $_[1]->() ) |
241 | ) { |
242 | |
243 | $cur_row_ids[$_] = defined $cur_row->[$_] ? $cur_row->[$_] : "\xFF\xFFN\xFFU\xFFL\xFFL\xFF\xFF" |
244 | for (0, 1, 5, 6, 8); |
245 | |
246 | $is_new_res = ! $collapse_idx[1]{$cur_row_ids[1]} and ( |
247 | $_[1] and $result_pos and (unshift @{$_[2]}, $cur_row) and last |
248 | ); |
249 | |
250 | $collapse_idx[1]{$cur_row_ids[1]} ||= [{ latest_cd => $cur_row->[7], year => $cur_row->[3], genreid => $cur_row->[4] }]; |
251 | |
252 | $collapse_idx[1]{$cur_row_ids[1]}[1]{existing_single_track} ||= $collapse_idx[2]{$cur_row_ids[1]}; |
253 | $collapse_idx[2]{$cur_row_ids[1]}[1]{cd} ||= $collapse_idx[3]{$cur_row_ids[1]}; |
254 | $collapse_idx[3]{$cur_row_ids[1]}[1]{artist} ||= $collapse_idx[4]{$cur_row_ids[1]} ||= [{ artistid => $cur_row->[1] }]; |
255 | |
256 | $collapse_idx[4]{$cur_row_ids[1]}[1]{cds} ||= []; |
257 | push @{ $collapse_idx[4]{$cur_row_ids[1]}[1]{cds} }, $collapse_idx[5]{$cur_row_ids[6]} ||= [{ cdid => $cur_row->[6], genreid => $cur_row->[9], year => $cur_row->[2] }] |
258 | unless $collapse_idx[5]{$cur_row_ids[6]}; |
259 | |
260 | $collapse_idx[5]{$cur_row_ids[6]}[1]{tracks} ||= []; |
261 | push @{ $collapse_idx[5]{$cur_row_ids[6]}[1]{tracks} }, $collapse_idx[6]{$cur_row_ids[6]}{$cur_row_ids[8]} ||= [{ title => $cur_row->[8] }] |
262 | unless $collapse_idx[6]{$cur_row_ids[6]}{$cur_row_ids[8]}; |
263 | |
264 | $collapse_idx[1]{$cur_row_ids[1]}[1]{tracks} ||= []; |
265 | push @{ $collapse_idx[1]{$cur_row_ids[1]}[1]{tracks} }, $collapse_idx[7]{$cur_row_ids[1]}{$cur_row_ids[5]} ||= [{ title => $cur_row->[5] }] |
266 | unless $collapse_idx[7]{$cur_row_ids[1]}{$cur_row_ids[5]}; |
267 | |
268 | $collapse_idx[7]{$cur_row_ids[1]}{$cur_row_ids[5]}[1]{lyrics} ||= $collapse_idx[8]{$cur_row_ids[1]}{$cur_row_ids[5] }; |
269 | |
270 | $collapse_idx[8]{$cur_row_ids[1]}{$cur_row_ids[5]}[1]{lyric_versions} ||= []; |
271 | push @{ $collapse_idx[8]{$cur_row_ids[1]}{$cur_row_ids[5]}[1]{lyric_versions} }, $collapse_idx[9]{$cur_row_ids[0]}{$cur_row_ids[1]}{$cur_row_ids[5]} ||= [{ text => $cur_row->[0] }] |
272 | unless $collapse_idx[9]{$cur_row_ids[0]}{$cur_row_ids[1]}{$cur_row_ids[5]}; |
273 | |
274 | $_[0][$result_pos++] = $collapse_idx[1]{$cur_row_ids[1]} |
275 | if $is_new_res; |
276 | } |
277 | |
278 | splice @{$_[0]}, $result_pos; |
279 | ', |
280 | 'Multiple has_many on multiple branches torture test', |
281 | ); |
282 | |
283 | done_testing; |
284 | |
285 | my $deparser; |
286 | sub is_same_src { |
287 | $deparser ||= B::Deparse->new; |
288 | local $Test::Builder::Level = $Test::Builder::Level + 1; |
289 | |
290 | my ($got, $expect) = map { |
291 | my $cref = eval "sub { $_ }" or do { |
292 | fail "Coderef does not compile!\n\n$@\n\n$_"; |
293 | return undef; |
294 | }; |
295 | $deparser->coderef2text($cref); |
296 | } @_[0,1]; |
297 | |
298 | is ($got, $expect, $_[2]||() ) |
299 | or note ("Originals source:\n\n$_[0]\n\n$_[1]\n"); |
300 | } |
301 | |