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