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