Add internal assertion guard for some indirect calls (for now only create/new)
[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
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
14use Data::Dumper;
15$Data::Dumper::Sortkeys = 1;
16
4e9fc3f3 17my $schema = DBICTest->init_schema(no_deploy => 1);
ce556881 18my $infmap = [qw/
19 single_track.cd.artist.name
20 year
21/];
4e9fc3f3 22
23is_same_src (
02a73c96 24 ($schema->source ('CD')->_mk_row_parser({
4e9fc3f3 25 inflate_map => $infmap,
02a73c96 26 }))[0],
4e9fc3f3 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 62is_same_src (
02a73c96 63 ($schema->source ('CD')->_mk_row_parser({
ce556881 64 inflate_map => $infmap,
02a73c96 65 }))[0],
ce556881 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
139is_same_src (
02a73c96 140 ($schema->source ('CD')->_mk_row_parser({
79adc44f 141 prune_null_branches => 1,
142 inflate_map => $infmap,
02a73c96 143 }))[0],
79adc44f 144 '$_ = [
145 { artist => $_->[5], title => $_->[4], year => $_->[2] },
146 {
147 single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) ) ? undef : [
148 undef,
149 {
150 cd => [
151 undef,
152 {
153 artist => [
154 { artistid => $_->[1] },
155 {
156 cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) ) ? undef : [
157 { cdid => $_->[3] },
158 {
159 tracks => ( ! defined $_->[0] ) ? undef : [
160 { title => $_->[0] },
161 ]
162 }
163 ]
164 }
165 ]
166 }
167 ]
168 }
169 ]
170 }
171 ] for @{$_[0]}',
172 '1:1 descending non-collapsing pruning parser terminating with chained 1:M:M',
173);
174
175is_same_src (
02a73c96 176 ($schema->source ('CD')->_mk_row_parser({
ce556881 177 hri_style => 1,
79adc44f 178 prune_null_branches => 1,
ce556881 179 inflate_map => $infmap,
02a73c96 180 }))[0],
ce556881 181 '$_ = {
182 artist => $_->[5], title => $_->[4], year => $_->[2],
183
52864fbd 184 ( single_track => ( (! defined $_->[0] ) && (! defined $_->[1]) && (! defined $_->[3] ) )
185 ? undef
186 : {
ce556881 187 cd =>
188 {
189 artist => {
190 artistid => $_->[1],
52864fbd 191 ( cds => ( (! defined $_->[0] ) && ( ! defined $_->[3] ) )
192 ? undef
193 : {
ce556881 194 cdid => $_->[3],
52864fbd 195 ( tracks => ( ! defined $_->[0] )
196 ? undef
197 : { title => $_->[0] }
198 )
ce556881 199 }
52864fbd 200 )
ce556881 201 }
202 }
203 }
52864fbd 204 )
ce556881 205 } for @{$_[0]}',
52864fbd 206 '1:1 descending non-collapsing HRI-direct parser terminating with chained 1:M:M',
ce556881 207);
208
209
210
4e9fc3f3 211is_deeply (
3faac878 212 ($schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} })),
4e9fc3f3 213 {
9f98c4b2 214 -identifying_columns => [ 4, 5 ],
4e9fc3f3 215
216 single_track => {
a0726a33 217 -identifying_columns => [ 1, 4, 5 ],
4e9fc3f3 218 -is_optional => 1,
219 -is_single => 1,
220
221 cd => {
a0726a33 222 -identifying_columns => [ 1, 4, 5 ],
4e9fc3f3 223 -is_single => 1,
224
225 artist => {
a0726a33 226 -identifying_columns => [ 1, 4, 5 ],
4e9fc3f3 227 -is_single => 1,
228
229 cds => {
a0726a33 230 -identifying_columns => [ 1, 3, 4, 5 ],
4e9fc3f3 231 -is_optional => 1,
232
233 tracks => {
a0726a33 234 -identifying_columns => [ 0, 1, 3, 4, 5 ],
4e9fc3f3 235 -is_optional => 1,
236 },
237 },
238 },
239 },
240 },
241 },
242 'Correct collapse map for 1:1 descending chain terminating with chained 1:M:M'
243);
244
245is_same_src (
02a73c96 246 ($schema->source ('CD')->_mk_row_parser({
4e9fc3f3 247 inflate_map => $infmap,
248 collapse => 1,
02a73c96 249 }))[0],
aa1d8a87 250 ' my $rows_pos = 0;
251 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
4e9fc3f3 252
9f98c4b2 253 while ($cur_row_data = (
3b4cd124 254 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
4e9fc3f3 255 ||
3b4cd124 256 ( $_[1] and $rows_pos = -1 and $_[1]->() )
257 ) ) {
4e9fc3f3 258
cd784aab 259 $cur_row_ids{0} = $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0";
260 $cur_row_ids{1} = $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0";
261 $cur_row_ids{3} = $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0";
262 $cur_row_ids{4} = $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0";
263 $cur_row_ids{5} = $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0";
4e9fc3f3 264
3faac878 265 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
aa1d8a87 266 $_[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 267
3faac878 268 # the rowdata itself for root node
cd784aab 269 $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 270
271 # prefetch data of single_track (placed in root)
cd784aab 272 $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 273 defined($cur_row_data->[1]) or bless( $collapse_idx[0]{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{single_track}, __NBC__ );
3faac878 274
275 # prefetch data of cd (placed in single_track)
cd784aab 276 $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 277
3faac878 278 # prefetch data of artist ( placed in single_track->cd)
cd784aab 279 $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 280
281 # prefetch data of cds (if available)
ce556881 282 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
283 and
284 push @{$collapse_idx[3]{$cur_row_ids{1}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{cds}}, (
285 $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} = [{ cdid => $cur_row_data->[3] }]
286 );
52864fbd 287 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 288
3faac878 289 # prefetch data of tracks (if available)
ce556881 290 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}} )
291 and
292 push @{$collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{3}}{$cur_row_ids{4}}{$cur_row_ids{5}}[1]{tracks}}, (
293 $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] }]
294 );
52864fbd 295 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 296
4e9fc3f3 297 }
aa1d8a87 298 $#{$_[0]} = $result_pos - 1;
4e9fc3f3 299 ',
300 'Same 1:1 descending terminating with chained 1:M:M but with collapse',
301);
302
ce556881 303is_same_src (
02a73c96 304 ($schema->source ('CD')->_mk_row_parser({
ce556881 305 inflate_map => $infmap,
306 collapse => 1,
ce556881 307 hri_style => 1,
79adc44f 308 prune_null_branches => 1,
02a73c96 309 }))[0],
aa1d8a87 310 ' my $rows_pos = 0;
311 my ($result_pos, @collapse_idx, $cur_row_data);
ce556881 312
313 while ($cur_row_data = (
3b4cd124 314 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
ce556881 315 ||
3b4cd124 316 ( $_[1] and $rows_pos = -1 and $_[1]->() )
317 ) ) {
ce556881 318
ce556881 319 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
aa1d8a87 320 $_[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 321
322 # the rowdata itself for root node
cd784aab 323 $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 324
325 # prefetch data of single_track (placed in root)
7596ddca 326 (! defined($cur_row_data->[1]) ) ? $collapse_idx[0]{$cur_row_data->[4]}{$cur_row_data->[5]}{single_track} = undef : do {
cd784aab 327 $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 328
7596ddca 329 # prefetch data of cd (placed in single_track)
cd784aab 330 $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 331
7596ddca 332 # prefetch data of artist ( placed in single_track->cd)
cd784aab 333 $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 334
7596ddca 335 # prefetch data of cds (if available)
336 (! defined $cur_row_data->[3] ) ? $collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cds} = [] : do {
ce556881 337
7596ddca 338 (! $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} )
339 and
340 push @{$collapse_idx[3]{$cur_row_data->[1]}{$cur_row_data->[4]}{$cur_row_data->[5]}{cds}}, (
341 $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} = { cdid => $cur_row_data->[3] }
342 );
ce556881 343
7596ddca 344 # prefetch data of tracks (if available)
345 ( ! 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 {
346
347 (! $collapse_idx[5]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]} )
348 and
349 push @{$collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[3]}{$cur_row_data->[4]}{$cur_row_data->[5]}{tracks}}, (
350 $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] }
351 );
352 };
353 };
354 };
ce556881 355 }
aa1d8a87 356 $#{$_[0]} = $result_pos - 1;
ce556881 357 ',
52864fbd 358 'Same 1:1 descending terminating with chained 1:M:M but with collapse, HRI-direct',
ce556881 359);
360
4e9fc3f3 361$infmap = [qw/
3d8caf63 362 tracks.lyrics.existing_lyric_versions.text
4e9fc3f3 363 existing_single_track.cd.artist.artistid
364 existing_single_track.cd.artist.cds.year
365 year
366 genreid
367 tracks.title
368 existing_single_track.cd.artist.cds.cdid
369 latest_cd
370 existing_single_track.cd.artist.cds.tracks.title
371 existing_single_track.cd.artist.cds.genreid
3d8caf63 372 tracks.lyrics.existing_lyric_versions.lyric_id
4e9fc3f3 373/];
374
375is_deeply (
82f0e0aa 376 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
4e9fc3f3 377 {
9f98c4b2 378 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
4e9fc3f3 379
380 existing_single_track => {
9f98c4b2 381 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
4e9fc3f3 382 -is_single => 1,
383
384 cd => {
9f98c4b2 385 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
4e9fc3f3 386 -is_single => 1,
387
388 artist => {
9f98c4b2 389 -identifying_columns => [ 1 ], # existing_single_track.cd.artist.artistid
4e9fc3f3 390 -is_single => 1,
391
392 cds => {
9f98c4b2 393 -identifying_columns => [ 1, 6 ], # existing_single_track.cd.artist.cds.cdid
4e9fc3f3 394 -is_optional => 1,
395
396 tracks => {
9f98c4b2 397 -identifying_columns => [ 1, 6, 8 ], # existing_single_track.cd.artist.cds.cdid, existing_single_track.cd.artist.cds.tracks.title
4e9fc3f3 398 -is_optional => 1,
399 }
400 }
401 }
402 }
403 },
404 tracks => {
9f98c4b2 405 -identifying_columns => [ 1, 5 ], # existing_single_track.cd.artist.artistid, tracks.title
4e9fc3f3 406 -is_optional => 1,
407
408 lyrics => {
3d8caf63 409 -identifying_columns => [ 1, 5, 10 ], # existing_single_track.cd.artist.artistid, tracks.title, tracks.lyrics.existing_lyric_versions.lyric_id
4e9fc3f3 410 -is_single => 1,
411 -is_optional => 1,
412
3d8caf63 413 existing_lyric_versions => {
414 -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 415 },
416 },
417 }
418 },
419 'Correct collapse map constructed',
420);
421
422is_same_src (
02a73c96 423 ($schema->source ('CD')->_mk_row_parser({
4e9fc3f3 424 inflate_map => $infmap,
425 collapse => 1,
02a73c96 426 }))[0],
aa1d8a87 427 ' my $rows_pos = 0;
428 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
4e9fc3f3 429
9f98c4b2 430 while ($cur_row_data = (
3b4cd124 431 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
4e9fc3f3 432 ||
3b4cd124 433 ( $_[1] and $rows_pos = -1 and $_[1]->() )
434 ) ) {
4e9fc3f3 435
cd784aab 436 $cur_row_ids{0} = $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0";
437 $cur_row_ids{1} = $cur_row_data->[1] // "\0NULL\xFF$rows_pos\xFF1\0";
438 $cur_row_ids{5} = $cur_row_data->[5] // "\0NULL\xFF$rows_pos\xFF5\0";
439 $cur_row_ids{6} = $cur_row_data->[6] // "\0NULL\xFF$rows_pos\xFF6\0";
440 $cur_row_ids{8} = $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0";
441 $cur_row_ids{10} = $cur_row_data->[10] // "\0NULL\xFF$rows_pos\xFF10\0";
4e9fc3f3 442
9f98c4b2 443 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
aa1d8a87 444 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{1}} and (unshift @{$_[2]}, $cur_row_data) and last;
4e9fc3f3 445
cd784aab 446 $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 447
cd784aab 448 $collapse_idx[0]{$cur_row_ids{1}}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_ids{1}} = [];
449 $collapse_idx[1]{$cur_row_ids{1}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{1}} = [];
450 $collapse_idx[2]{$cur_row_ids{1}}[1]{artist} //= $collapse_idx[3]{$cur_row_ids{1}} = [{ artistid => $cur_row_data->[1] }];
4e9fc3f3 451
ce556881 452 (! $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}} )
453 and
454 push @{ $collapse_idx[3]{$cur_row_ids{1}}[1]{cds} }, (
455 $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] }]
456 );
52864fbd 457 defined($cur_row_data->[6]) or bless( $collapse_idx[3]{$cur_row_ids{1}}[1]{cds}, __NBC__ );
4e9fc3f3 458
ce556881 459 (! $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} )
460 and
461 push @{ $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks} }, (
462 $collapse_idx[5]{$cur_row_ids{1}}{$cur_row_ids{6}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
463 );
52864fbd 464 defined($cur_row_data->[8]) or bless( $collapse_idx[4]{$cur_row_ids{1}}{$cur_row_ids{6}}[1]{tracks}, __NBC__ );
4e9fc3f3 465
ce556881 466 (! $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} )
467 and
468 push @{ $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks} }, (
469 $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}} = [{ title => $cur_row_data->[5] }]
470 );
52864fbd 471 defined($cur_row_data->[5]) or bless( $collapse_idx[0]{$cur_row_ids{1}}[1]{tracks}, __NBC__ );
4e9fc3f3 472
cd784aab 473 $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 474 defined($cur_row_data->[10]) or bless( $collapse_idx[6]{$cur_row_ids{1}}{$cur_row_ids{5}}[1]{lyrics}, __NBC__ );
4e9fc3f3 475
ce556881 476 (! $collapse_idx[8]{$cur_row_ids{0}}{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}} )
477 and
478 push @{ $collapse_idx[7]{$cur_row_ids{1}}{$cur_row_ids{5}}{$cur_row_ids{10}}[1]{existing_lyric_versions} }, (
479 $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] }]
480 );
4e9fc3f3 481 }
482
aa1d8a87 483 $#{$_[0]} = $result_pos - 1;
4e9fc3f3 484 ',
485 'Multiple has_many on multiple branches torture test',
486);
487
ce556881 488is_same_src (
02a73c96 489 ($schema->source ('CD')->_mk_row_parser({
ce556881 490 inflate_map => $infmap,
491 collapse => 1,
79adc44f 492 prune_null_branches => 1,
02a73c96 493 }))[0],
aa1d8a87 494 ' my $rows_pos = 0;
79adc44f 495 my ($result_pos, @collapse_idx, $cur_row_data);
ce556881 496
497 while ($cur_row_data = (
3b4cd124 498 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
ce556881 499 ||
3b4cd124 500 ( $_[1] and $rows_pos = -1 and $_[1]->() )
501 ) ) {
ce556881 502
ce556881 503 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
79adc44f 504 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_data->[1]} and (unshift @{$_[2]}, $cur_row_data) and last;
ce556881 505
cd784aab 506 $collapse_idx[0]{$cur_row_data->[1]} //= $_[0][$result_pos++] = [{ genreid => $cur_row_data->[4], latest_cd => $cur_row_data->[7], year => $cur_row_data->[3] }];
ce556881 507
cd784aab 508 $collapse_idx[0]{$cur_row_data->[1]}[1]{existing_single_track} //= $collapse_idx[1]{$cur_row_data->[1]} = [];
509 $collapse_idx[1]{$cur_row_data->[1]}[1]{cd} //= $collapse_idx[2]{$cur_row_data->[1]} = [];
510 $collapse_idx[2]{$cur_row_data->[1]}[1]{artist} //= $collapse_idx[3]{$cur_row_data->[1]} = [{ artistid => $cur_row_data->[1] }];
ce556881 511
79adc44f 512 (! defined($cur_row_data->[6])) ? $collapse_idx[3]{$cur_row_data->[1]}[1]{cds} = [] : do {
513 (! $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]} )
514 and
515 push @{ $collapse_idx[3]{$cur_row_data->[1]}[1]{cds} }, (
516 $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]} = [{ cdid => $cur_row_data->[6], genreid => $cur_row_data->[9], year => $cur_row_data->[2] }]
517 );
ce556881 518
79adc44f 519 (! defined($cur_row_data->[8]) ) ? $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]}[1]{tracks} = [] : do {
ce556881 520
79adc44f 521 (! $collapse_idx[5]{$cur_row_data->[1]}{$cur_row_data->[6]}{$cur_row_data->[8]} )
522 and
523 push @{ $collapse_idx[4]{$cur_row_data->[1]}{$cur_row_data->[6]}[1]{tracks} }, (
524 $collapse_idx[5]{$cur_row_data->[1]}{$cur_row_data->[6]}{$cur_row_data->[8]} = [{ title => $cur_row_data->[8] }]
525 );
526 };
527 };
ce556881 528
79adc44f 529 (! defined($cur_row_data->[5]) ) ? $collapse_idx[0]{$cur_row_data->[1]}[1]{tracks} = [] : do {
ce556881 530
79adc44f 531 (! $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]} )
532 and
533 push @{ $collapse_idx[0]{$cur_row_data->[1]}[1]{tracks} }, (
534 $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]} = [{ title => $cur_row_data->[5] }]
535 );
536
537 (! defined($cur_row_data->[10]) ) ? $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]}[1]{lyrics} = [] : do {
538
cd784aab 539 $collapse_idx[6]{$cur_row_data->[1]}{$cur_row_data->[5]}[1]{lyrics} //= $collapse_idx[7]{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]} = [];
79adc44f 540
541 (! $collapse_idx[8]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]} )
542 and
543 push @{ $collapse_idx[7]{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]}[1]{existing_lyric_versions} }, (
544 $collapse_idx[8]{$cur_row_data->[0]}{$cur_row_data->[1]}{$cur_row_data->[5]}{$cur_row_data->[10]} = [{ lyric_id => $cur_row_data->[10], text => $cur_row_data->[0] }]
545 );
546 };
547 };
ce556881 548 }
549
aa1d8a87 550 $#{$_[0]} = $result_pos - 1;
ce556881 551 ',
79adc44f 552 'Multiple has_many on multiple branches with branch pruning torture test',
ce556881 553);
554
fcf32d04 555$infmap = [
556 'single_track.trackid', # (0) definitive link to root from 1:1:1:1:M:M chain
557 'year', # (1) non-unique
558 'tracks.cd', # (2) \ together both uniqueness for second multirel
559 'tracks.title', # (3) / and definitive link back to root
560 'single_track.cd.artist.cds.cdid', # (4) to give uniquiness to ...tracks.title below
561 'single_track.cd.artist.cds.year', # (5) non-unique
562 'single_track.cd.artist.artistid', # (6) uniqufies entire parental chain
563 'single_track.cd.artist.cds.genreid', # (7) nullable
564 'single_track.cd.artist.cds.tracks.title',# (8) unique when combined with ...cds.cdid above
565];
566
567is_deeply (
568 $schema->source('CD')->_resolve_collapse({ as => {map { $infmap->[$_] => $_ } 0 .. $#$infmap} }),
569 {
9f98c4b2 570 -identifying_columns => [],
571 -identifying_columns_variants => [
fcf32d04 572 [ 0 ], [ 2 ],
573 ],
574 single_track => {
9f98c4b2 575 -identifying_columns => [ 0 ],
fcf32d04 576 -is_optional => 1,
577 -is_single => 1,
fcf32d04 578 cd => {
9f98c4b2 579 -identifying_columns => [ 0 ],
fcf32d04 580 -is_single => 1,
fcf32d04 581 artist => {
9f98c4b2 582 -identifying_columns => [ 0 ],
fcf32d04 583 -is_single => 1,
fcf32d04 584 cds => {
9f98c4b2 585 -identifying_columns => [ 0, 4 ],
fcf32d04 586 -is_optional => 1,
fcf32d04 587 tracks => {
9f98c4b2 588 -identifying_columns => [ 0, 4, 8 ],
fcf32d04 589 -is_optional => 1,
fcf32d04 590 }
591 }
592 }
593 }
594 },
595 tracks => {
9f98c4b2 596 -identifying_columns => [ 2, 3 ],
fcf32d04 597 -is_optional => 1,
fcf32d04 598 }
599 },
600 'Correct underdefined root collapse map constructed'
601);
602
603is_same_src (
02a73c96 604 ($schema->source ('CD')->_mk_row_parser({
fcf32d04 605 inflate_map => $infmap,
606 collapse => 1,
02a73c96 607 }))[0],
aa1d8a87 608 ' my $rows_pos = 0;
609 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
fcf32d04 610
9f98c4b2 611 while ($cur_row_data = (
3b4cd124 612 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
fcf32d04 613 ||
3b4cd124 614 ( $_[1] and $rows_pos = -1 and $_[1]->() )
615 ) ) {
fcf32d04 616
cd784aab 617 $cur_row_ids{0} = $cur_row_data->[0] // "\0NULL\xFF$rows_pos\xFF0\0";
618 $cur_row_ids{2} = $cur_row_data->[2] // "\0NULL\xFF$rows_pos\xFF2\0";
619 $cur_row_ids{3} = $cur_row_data->[3] // "\0NULL\xFF$rows_pos\xFF3\0";
620 $cur_row_ids{4} = $cur_row_data->[4] // "\0NULL\xFF$rows_pos\xFF4\0";
621 $cur_row_ids{8} = $cur_row_data->[8] // "\0NULL\xFF$rows_pos\xFF8\0";
fcf32d04 622
623 # cache expensive set of ops in a non-existent rowid slot
9f98c4b2 624 $cur_row_ids{10} = (
625 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} ))
fcf32d04 626 or
9f98c4b2 627 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} ))
fcf32d04 628 or
629 "\0$rows_pos\0"
630 );
631
9f98c4b2 632 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
aa1d8a87 633 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last;
fcf32d04 634
cd784aab 635 $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = [{ year => $$cur_row_data[1] }];
fcf32d04 636
cd784aab 637 $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = [{ trackid => $cur_row_data->[0] }]);
52864fbd 638 defined($cur_row_data->[0]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{single_track}, __NBC__ );
fcf32d04 639
cd784aab 640 $collapse_idx[1]{$cur_row_ids{0}}[1]{cd} //= $collapse_idx[2]{$cur_row_ids{0}} = [];
fcf32d04 641
cd784aab 642 $collapse_idx[2]{$cur_row_ids{0}}[1]{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = [{ artistid => $cur_row_data->[6] }]);
fcf32d04 643
ce556881 644 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
645 and
646 push @{$collapse_idx[3]{$cur_row_ids{0}}[1]{cds}}, (
52864fbd 647 $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 648 );
52864fbd 649 defined($cur_row_data->[4]) or bless ( $collapse_idx[3]{$cur_row_ids{0}}[1]{cds}, __NBC__ );
fcf32d04 650
ce556881 651 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
652 and
653 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}}, (
52864fbd 654 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = [{ title => $cur_row_data->[8] }]
ce556881 655 );
52864fbd 656 defined($cur_row_data->[8]) or bless ( $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}[1]{tracks}, __NBC__ );
fcf32d04 657
ce556881 658 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
659 and
660 push @{$collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}}, (
52864fbd 661 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = [{ cd => $$cur_row_data[2], title => $cur_row_data->[3] }]
ce556881 662 );
52864fbd 663 defined($cur_row_data->[2]) or bless ( $collapse_idx[0]{$cur_row_ids{10}}[1]{tracks}, __NBC__ );
fcf32d04 664 }
665
aa1d8a87 666 $#{$_[0]} = $result_pos - 1;
fcf32d04 667 ',
668 'Multiple has_many on multiple branches with underdefined root torture test',
669);
670
ce556881 671is_same_src (
02a73c96 672 ($schema->source ('CD')->_mk_row_parser({
ce556881 673 inflate_map => $infmap,
674 collapse => 1,
ce556881 675 hri_style => 1,
79adc44f 676 prune_null_branches => 1,
02a73c96 677 }))[0],
aa1d8a87 678 ' my $rows_pos = 0;
06b3406d 679 my ($result_pos, @collapse_idx, $cur_row_data, %cur_row_ids);
ce556881 680
681 while ($cur_row_data = (
3b4cd124 682 ( $rows_pos >= 0 and $_[0][$rows_pos++] )
ce556881 683 ||
3b4cd124 684 ( $_[1] and $rows_pos = -1 and $_[1]->() )
685 ) ) {
686
5e6d06f4 687 # do not care about nullability here
688 $cur_row_ids{0} = $cur_row_data->[0];
689 $cur_row_ids{2} = $cur_row_data->[2];
690 $cur_row_ids{3} = $cur_row_data->[3];
691 $cur_row_ids{4} = $cur_row_data->[4];
692 $cur_row_ids{8} = $cur_row_data->[8];
06b3406d 693
ce556881 694 # cache expensive set of ops in a non-existent rowid slot
06b3406d 695 $cur_row_ids{10} = (
ce556881 696 ( ( defined $cur_row_data->[0] ) && (join "\xFF", q{}, $cur_row_data->[0], q{} ))
697 or
698 ( ( defined $cur_row_data->[2] ) && (join "\xFF", q{}, $cur_row_data->[2], q{} ))
699 or
700 "\0$rows_pos\0"
701 );
702
703 # a present cref in $_[1] implies lazy prefetch, implies a supplied stash in $_[2]
06b3406d 704 $_[1] and $result_pos and ! $collapse_idx[0]{$cur_row_ids{10}} and (unshift @{$_[2]}, $cur_row_data) and last;
ce556881 705
cd784aab 706 $collapse_idx[0]{$cur_row_ids{10}} //= $_[0][$result_pos++] = { year => $$cur_row_data[1] };
ce556881 707
06b3406d 708 (! defined $cur_row_data->[0] ) ? $collapse_idx[0]{$cur_row_ids{10}}{single_track} = undef : do {
ce556881 709
cd784aab 710 $collapse_idx[0]{$cur_row_ids{10}}{single_track} //= ($collapse_idx[1]{$cur_row_ids{0}} = { trackid => $$cur_row_data[0] });
ce556881 711
cd784aab 712 $collapse_idx[1]{$cur_row_ids{0}}{cd} //= $collapse_idx[2]{$cur_row_ids{0}};
ce556881 713
cd784aab 714 $collapse_idx[2]{$cur_row_ids{0}}{artist} //= ($collapse_idx[3]{$cur_row_ids{0}} = { artistid => $$cur_row_data[6] });
ce556881 715
06b3406d 716 (! defined $cur_row_data->[4] ) ? $collapse_idx[3]{$cur_row_ids{0}}{cds} = [] : do {
ce556881 717
06b3406d 718 (! $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}} )
7596ddca 719 and
06b3406d 720 push @{$collapse_idx[3]{$cur_row_ids{0}}{cds}}, (
721 $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 722 );
ce556881 723
06b3406d 724 (! defined $cur_row_data->[8] ) ? $collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks} = [] : do {
7596ddca 725
06b3406d 726 (! $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} )
7596ddca 727 and
06b3406d 728 push @{$collapse_idx[4]{$cur_row_ids{0}}{$cur_row_ids{4}}{tracks}}, (
729 $collapse_idx[5]{$cur_row_ids{0}}{$cur_row_ids{4}}{$cur_row_ids{8}} = { title => $$cur_row_data[8] }
7596ddca 730 );
731 };
732 };
733 };
734
06b3406d 735 (! defined $cur_row_data->[2] ) ? $collapse_idx[0]{$cur_row_ids{10}}{tracks} = [] : do {
736 (! $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} )
7596ddca 737 and
06b3406d 738 push @{$collapse_idx[0]{$cur_row_ids{10}}{tracks}}, (
739 $collapse_idx[6]{$cur_row_ids{2}}{$cur_row_ids{3}} = { cd => $$cur_row_data[2], title => $$cur_row_data[3] }
7596ddca 740 );
741 };
ce556881 742 }
743
aa1d8a87 744 $#{$_[0]} = $result_pos - 1;
ce556881 745 ',
52864fbd 746 'Multiple has_many on multiple branches with underdefined root, HRI-direct torture test',
ce556881 747);
748
4e9fc3f3 749done_testing;
750
751my $deparser;
cd784aab 752sub is_same_src { SKIP: {
4e9fc3f3 753 $deparser ||= B::Deparse->new;
754 local $Test::Builder::Level = $Test::Builder::Level + 1;
755
52864fbd 756 my ($got, $expect) = @_;
757
cd784aab 758 skip "Not testing equality of source containing defined-or operator on this perl $]", 1
759 if ($] < 5.010 and$expect =~ m!\Q//=!);
760
52864fbd 761 $expect =~ s/__NBC__/B::perlstring($DBIx::Class::ResultSource::RowParser::Util::null_branch_class)/ge;
762
bdbd2ae8 763 $expect = " { use strict; use warnings FATAL => 'all';\n$expect\n }";
764
52864fbd 765 my @normalized = map {
4e9fc3f3 766 my $cref = eval "sub { $_ }" or do {
767 fail "Coderef does not compile!\n\n$@\n\n$_";
768 return undef;
769 };
770 $deparser->coderef2text($cref);
52864fbd 771 } ($got, $expect);
772
773 &is (@normalized, $_[2]||() ) or do {
774 eval { require Test::Differences }
775 ? &Test::Differences::eq_or_diff( @normalized, $_[2]||() )
e81b50f4 776 : note ("Original sources:\n\n$got\n\n$expect\n")
777 ;
778 exit 1;
52864fbd 779 };
cd784aab 780} }