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