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