Hit an MC hash-order bug - simplify create, and solve it another time
[dbsrgits/DBIx-Class.git] / t / resultset / rowparser_internals.t
CommitLineData
4e9fc3f3 1use strict;
2use warnings;
3
4use Test::More;
5use lib qw(t/lib);
6use DBICTest;
7use B::Deparse;
8
9my $schema = DBICTest->init_schema(no_deploy => 1);
10my $infmap = [qw/single_track.cd.artist.name year/];
11
12is_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/];
39is_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
64is_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
110is_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
164is_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
230is_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
283done_testing;
284
285my $deparser;
286sub 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