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