| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package # hide from the pauses |
|
2
|
|
|
|
|
|
|
DBIx::Class::ResultSource::RowParser; |
|
3
|
|
|
|
|
|
|
|
|
4
|
436
|
|
|
436
|
|
3934
|
use strict; |
|
|
436
|
|
|
|
|
1464
|
|
|
|
436
|
|
|
|
|
12993
|
|
|
5
|
436
|
|
|
436
|
|
2660
|
use warnings; |
|
|
436
|
|
|
|
|
1387
|
|
|
|
436
|
|
|
|
|
12927
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
436
|
|
|
436
|
|
2616
|
use base 'DBIx::Class'; |
|
|
436
|
|
|
|
|
1524
|
|
|
|
436
|
|
|
|
|
59251
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
419
|
|
|
419
|
|
3737
|
use Try::Tiny; |
|
|
419
|
|
|
|
|
1466
|
|
|
|
419
|
|
|
|
|
27605
|
|
|
10
|
419
|
|
|
419
|
|
3240
|
use List::Util qw(first max); |
|
|
419
|
|
|
|
|
1409
|
|
|
|
419
|
|
|
|
|
32524
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
419
|
|
|
|
|
38558
|
use DBIx::Class::ResultSource::RowParser::Util qw( |
|
13
|
|
|
|
|
|
|
assemble_simple_parser |
|
14
|
|
|
|
|
|
|
assemble_collapsing_parser |
|
15
|
419
|
|
|
419
|
|
185343
|
); |
|
|
419
|
|
|
|
|
1454
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
381
|
|
|
381
|
|
3360
|
use namespace::clean; |
|
|
381
|
|
|
|
|
1278
|
|
|
|
381
|
|
|
|
|
2881
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# Accepts one or more relationships for the current source and returns an |
|
20
|
|
|
|
|
|
|
# array of column names for each of those relationships. Column names are |
|
21
|
|
|
|
|
|
|
# prefixed relative to the current source, in accordance with where they appear |
|
22
|
|
|
|
|
|
|
# in the supplied relationships. |
|
23
|
|
|
|
|
|
|
sub _resolve_prefetch { |
|
24
|
966
|
|
|
966
|
|
2847
|
my ($self, $pre, $alias, $alias_map, $order, $pref_path) = @_; |
|
25
|
966
|
|
100
|
|
|
3031
|
$pref_path ||= []; |
|
26
|
|
|
|
|
|
|
|
|
27
|
966
|
100
|
100
|
|
|
5765
|
if (not defined $pre or not length $pre) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
28
|
99
|
|
|
|
|
350
|
return (); |
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
elsif( ref $pre eq 'ARRAY' ) { |
|
31
|
|
|
|
|
|
|
return |
|
32
|
362
|
|
|
|
|
974
|
map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, [ @$pref_path ] ) } |
|
|
422
|
|
|
|
|
2568
|
|
|
33
|
|
|
|
|
|
|
@$pre; |
|
34
|
|
|
|
|
|
|
} |
|
35
|
|
|
|
|
|
|
elsif( ref $pre eq 'HASH' ) { |
|
36
|
|
|
|
|
|
|
my @ret = |
|
37
|
|
|
|
|
|
|
map { |
|
38
|
98
|
|
|
|
|
315
|
$self->_resolve_prefetch($_, $alias, $alias_map, $order, [ @$pref_path ] ), |
|
39
|
|
|
|
|
|
|
$self->related_source($_)->_resolve_prefetch( |
|
40
|
97
|
|
|
|
|
517
|
$pre->{$_}, "${alias}.$_", $alias_map, $order, [ @$pref_path, $_] ) |
|
41
|
|
|
|
|
|
|
} keys %$pre; |
|
42
|
98
|
|
|
|
|
672
|
return @ret; |
|
43
|
|
|
|
|
|
|
} |
|
44
|
|
|
|
|
|
|
elsif( ref $pre ) { |
|
45
|
1
|
|
|
|
|
4
|
$self->throw_exception( |
|
46
|
|
|
|
|
|
|
"don't know how to resolve prefetch reftype ".ref($pre)); |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
else { |
|
49
|
411
|
|
|
|
|
820
|
my $p = $alias_map; |
|
50
|
411
|
|
|
|
|
1567
|
$p = $p->{$_} for (@$pref_path, $pre); |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
$self->throw_exception ( |
|
53
|
|
|
|
|
|
|
"Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: " |
|
54
|
|
|
|
|
|
|
. join (' -> ', @$pref_path, $pre) |
|
55
|
411
|
50
|
33
|
|
|
1640
|
) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} ); |
|
|
411
|
|
|
|
|
1611
|
|
|
56
|
|
|
|
|
|
|
|
|
57
|
411
|
|
|
|
|
1101
|
my $as = shift @{$p->{-join_aliases}}; |
|
|
411
|
|
|
|
|
1080
|
|
|
58
|
|
|
|
|
|
|
|
|
59
|
411
|
|
|
|
|
1445
|
my $rel_info = $self->relationship_info( $pre ); |
|
60
|
411
|
50
|
|
|
|
1194
|
$self->throw_exception( $self->source_name . " has no such relationship '$pre'" ) |
|
61
|
|
|
|
|
|
|
unless $rel_info; |
|
62
|
|
|
|
|
|
|
|
|
63
|
411
|
100
|
|
|
|
2024
|
my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : ''); |
|
64
|
|
|
|
|
|
|
|
|
65
|
411
|
|
|
|
|
1410
|
return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] } |
|
|
1849
|
|
|
|
|
8794
|
|
|
66
|
|
|
|
|
|
|
$self->related_source($pre)->columns; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# Takes an arrayref of {as} dbic column aliases and the collapse and select |
|
71
|
|
|
|
|
|
|
# attributes from the same $rs (the selector requirement is a temporary |
|
72
|
|
|
|
|
|
|
# workaround... I hope), and returns a coderef capable of: |
|
73
|
|
|
|
|
|
|
# my $me_pref_clps = $coderef->([$rs->cursor->next/all]) |
|
74
|
|
|
|
|
|
|
# Where the $me_pref_clps arrayref is the future argument to inflate_result() |
|
75
|
|
|
|
|
|
|
# |
|
76
|
|
|
|
|
|
|
# For an example of this coderef in action (and to see its guts) look at |
|
77
|
|
|
|
|
|
|
# t/resultset/rowparser_internals.t |
|
78
|
|
|
|
|
|
|
# |
|
79
|
|
|
|
|
|
|
# This is a huge performance win, as we call the same code for every row |
|
80
|
|
|
|
|
|
|
# returned from the db, thus avoiding repeated method lookups when traversing |
|
81
|
|
|
|
|
|
|
# relationships |
|
82
|
|
|
|
|
|
|
# |
|
83
|
|
|
|
|
|
|
# Also since the coderef is completely stateless (the returned structure is |
|
84
|
|
|
|
|
|
|
# always fresh on every new invocation) this is a very good opportunity for |
|
85
|
|
|
|
|
|
|
# memoization if further speed improvements are needed |
|
86
|
|
|
|
|
|
|
# |
|
87
|
|
|
|
|
|
|
# The way we construct this coderef is somewhat fugly, although the result is |
|
88
|
|
|
|
|
|
|
# really worth it. The final coderef does not perform any kind of recursion - |
|
89
|
|
|
|
|
|
|
# the entire nested structure constructor is rolled out into a single scope. |
|
90
|
|
|
|
|
|
|
# |
|
91
|
|
|
|
|
|
|
# In any case - the output of this thing is meticulously micro-tested, so |
|
92
|
|
|
|
|
|
|
# any sort of adjustment/rewrite should be relatively easy (fsvo relatively) |
|
93
|
|
|
|
|
|
|
# |
|
94
|
|
|
|
|
|
|
sub _mk_row_parser { |
|
95
|
|
|
|
|
|
|
# $args and $attrs are separated to delineate what is core collapser stuff and |
|
96
|
|
|
|
|
|
|
# what is dbic $rs specific |
|
97
|
234
|
|
|
235
|
|
859
|
my ($self, $args, $attrs) = @_; |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
die "HRI without pruning makes zero sense" |
|
100
|
234
|
50
|
66
|
|
|
1163
|
if ( $args->{hri_style} && ! $args->{prune_null_branches} ); |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
my %common = ( |
|
103
|
|
|
|
|
|
|
hri_style => $args->{hri_style}, |
|
104
|
|
|
|
|
|
|
prune_null_branches => $args->{prune_null_branches}, |
|
105
|
|
|
|
|
|
|
val_index => { map |
|
106
|
2215
|
|
|
|
|
5690
|
{ $args->{inflate_map}[$_] => $_ } |
|
107
|
234
|
|
|
|
|
1273
|
( 0 .. $#{$args->{inflate_map}} ) |
|
|
234
|
|
|
|
|
847
|
|
|
108
|
|
|
|
|
|
|
}, |
|
109
|
|
|
|
|
|
|
); |
|
110
|
|
|
|
|
|
|
|
|
111
|
234
|
|
|
|
|
840
|
my $check_null_columns; |
|
112
|
|
|
|
|
|
|
|
|
113
|
234
|
100
|
|
|
|
1113
|
my $src = (! $args->{collapse} ) ? assemble_simple_parser(\%common) : do { |
|
114
|
|
|
|
|
|
|
my $collapse_map = $self->_resolve_collapse ({ |
|
115
|
|
|
|
|
|
|
# FIXME |
|
116
|
|
|
|
|
|
|
# only consider real columns (not functions) during collapse resolution |
|
117
|
|
|
|
|
|
|
# this check shouldn't really be here, as fucktards are not supposed to |
|
118
|
|
|
|
|
|
|
# alias random crap to existing column names anyway, but still - just in |
|
119
|
|
|
|
|
|
|
# case |
|
120
|
|
|
|
|
|
|
# FIXME !!!! - this does not yet deal with unbalanced selectors correctly |
|
121
|
|
|
|
|
|
|
# (it is now trivial as the attrs specify where things go out of sync |
|
122
|
|
|
|
|
|
|
# needs MOAR tests) |
|
123
|
|
|
|
|
|
|
as => { map |
|
124
|
1653
|
100
|
|
|
|
5415
|
{ ref $attrs->{select}[$common{val_index}{$_}] ? () : ( $_ => $common{val_index}{$_} ) } |
|
125
|
166
|
|
|
|
|
799
|
keys %{$common{val_index}} |
|
126
|
|
|
|
|
|
|
}, |
|
127
|
|
|
|
|
|
|
premultiplied => $args->{premultiplied}, |
|
128
|
166
|
|
|
|
|
462
|
}); |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
$check_null_columns = $collapse_map->{-identifying_columns} |
|
131
|
166
|
100
|
|
|
|
836
|
if @{$collapse_map->{-identifying_columns}}; |
|
|
166
|
|
|
|
|
901
|
|
|
132
|
|
|
|
|
|
|
|
|
133
|
166
|
|
|
|
|
1464
|
assemble_collapsing_parser({ |
|
134
|
|
|
|
|
|
|
%common, |
|
135
|
|
|
|
|
|
|
collapse_map => $collapse_map, |
|
136
|
|
|
|
|
|
|
}); |
|
137
|
|
|
|
|
|
|
}; |
|
138
|
|
|
|
|
|
|
|
|
139
|
234
|
|
|
|
|
934
|
utf8::upgrade($src) |
|
140
|
|
|
|
|
|
|
if DBIx::Class::_ENV_::STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE; |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
return ( |
|
143
|
234
|
100
|
50
|
41
|
|
24640
|
$args->{eval} ? ( eval "sub $src" || die $@ ) : $src, |
|
|
41
|
|
|
41
|
|
411
|
|
|
|
41
|
|
|
41
|
|
105
|
|
|
|
41
|
|
|
31
|
|
1455
|
|
|
|
41
|
|
|
31
|
|
331
|
|
|
|
41
|
|
|
31
|
|
147
|
|
|
|
41
|
|
|
1
|
|
2170
|
|
|
|
41
|
|
|
1
|
|
415
|
|
|
|
41
|
|
|
1
|
|
121
|
|
|
|
41
|
|
|
1
|
|
14831
|
|
|
|
31
|
|
|
1
|
|
355
|
|
|
|
31
|
|
|
1
|
|
100
|
|
|
|
31
|
|
|
1
|
|
1035
|
|
|
|
31
|
|
|
1
|
|
227
|
|
|
|
31
|
|
|
1
|
|
82
|
|
|
|
31
|
|
|
1
|
|
1375
|
|
|
|
31
|
|
|
1
|
|
397
|
|
|
|
31
|
|
|
1
|
|
85
|
|
|
|
31
|
|
|
1
|
|
9421
|
|
|
|
1
|
|
|
1
|
|
26
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
3
|
|
|
|
1
|
|
|
1
|
|
36
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
265
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
35
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
235
|
|
|
|
1
|
|
|
1
|
|
9
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
26
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
36
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
3
|
|
|
|
1
|
|
|
1
|
|
239
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
3
|
|
|
|
1
|
|
|
1
|
|
24
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
35
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
266
|
|
|
|
1
|
|
|
1
|
|
9
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
33
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
115
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
34
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
180
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
35
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
1
|
|
|
|
1
|
|
|
1
|
|
148
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
23
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
35
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
178
|
|
|
|
1
|
|
|
1
|
|
9
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
28
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
37
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
316
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
3
|
|
|
|
1
|
|
|
1
|
|
26
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
1
|
|
|
|
1
|
|
|
1
|
|
37
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
310
|
|
|
|
1
|
|
|
1
|
|
10
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
38
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
275
|
|
|
|
1
|
|
|
1
|
|
9
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
34
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
120
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
3
|
|
|
|
1
|
|
|
1
|
|
26
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
438
|
|
|
|
1
|
|
|
1
|
|
49
|
|
|
|
1
|
|
|
1
|
|
6
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
271
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
3
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
4
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
35
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
270
|
|
|
|
1
|
|
|
1
|
|
8
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
6
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
36
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
1
|
|
|
|
1
|
|
|
1
|
|
148
|
|
|
|
1
|
|
|
1
|
|
10
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
1
|
|
25
|
|
|
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
1
|
|
2
|
|
|
|
1
|
|
|
|
|
37
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
278
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
25
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
37
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
185
|
|
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
26
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
34
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
231
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
24
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
33
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
230
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
25
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
35
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
270
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
25
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
35
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
149
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
27
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
35
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
196
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
57
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
35
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
119
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
26
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
34
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
145
|
|
|
|
1
|
|
|
|
|
9
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
26
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
36
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
327
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
24
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
34
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
208
|
|
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
23
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
32
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
112
|
|
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
23
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
32
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
222
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
26
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
32
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
115
|
|
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
25
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
34
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
245
|
|
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
25
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
31
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
110
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
25
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
35
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
226
|
|
|
|
1
|
|
|
|
|
9
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
25
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
33
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
172
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
21
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
26
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
226
|
|
|
|
1
|
|
|
|
|
10
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
29
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
41
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
144
|
|
|
|
1
|
|
|
|
|
12
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
31
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
40
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
327
|
|
|
144
|
|
|
|
|
|
|
$check_null_columns, |
|
145
|
|
|
|
|
|
|
); |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# Takes an arrayref selection list and generates a collapse-map representing |
|
150
|
|
|
|
|
|
|
# row-object fold-points. Every relationship is assigned a set of unique, |
|
151
|
|
|
|
|
|
|
# non-nullable columns (which may *not even be* from the same resultset) |
|
152
|
|
|
|
|
|
|
# and the collapser will use this information to correctly distinguish |
|
153
|
|
|
|
|
|
|
# data of individual to-be-row-objects. See t/resultset/rowparser_internals.t |
|
154
|
|
|
|
|
|
|
# for extensive RV examples |
|
155
|
|
|
|
|
|
|
sub _resolve_collapse { |
|
156
|
561
|
|
|
561
|
|
1724
|
my ($self, $args, $common_args) = @_; |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# for comprehensible error messages put ourselves at the head of the relationship chain |
|
159
|
561
|
|
100
|
|
|
2657
|
$args->{_rel_chain} ||= [ $self->source_name ]; |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# record top-level fully-qualified column index, signify toplevelness |
|
162
|
561
|
100
|
|
|
|
1863
|
unless ($common_args->{_as_fq_idx}) { |
|
163
|
169
|
|
|
|
|
384
|
$common_args->{_as_fq_idx} = { %{$args->{as}} }; |
|
|
169
|
|
|
|
|
1230
|
|
|
164
|
169
|
|
|
|
|
688
|
$args->{_is_top_level} = 1; |
|
165
|
|
|
|
|
|
|
}; |
|
166
|
|
|
|
|
|
|
|
|
167
|
561
|
|
|
|
|
1090
|
my ($my_cols, $rel_cols); |
|
168
|
561
|
|
|
|
|
927
|
for (keys %{$args->{as}}) { |
|
|
561
|
|
|
|
|
2266
|
|
|
169
|
3675
|
100
|
|
|
|
10196
|
if ($_ =~ /^ ([^\.]+) \. (.+) /x) { |
|
170
|
1953
|
|
|
|
|
5886
|
$rel_cols->{$1}{$2} = 1; |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
else { |
|
173
|
1723
|
|
|
|
|
3918
|
$my_cols->{$_} = {}; # important for ||='s below |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
|
|
177
|
561
|
|
|
|
|
1278
|
my $relinfo; |
|
178
|
|
|
|
|
|
|
# run through relationships, collect metadata |
|
179
|
561
|
|
|
|
|
1664
|
for my $rel (keys %$rel_cols) { |
|
180
|
379
|
|
|
|
|
1703
|
my $inf = $self->relationship_info ($rel); |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
$relinfo->{$rel} = { |
|
183
|
|
|
|
|
|
|
is_single => ( $inf->{attrs}{accessor} && $inf->{attrs}{accessor} ne 'multi' ), |
|
184
|
379
|
|
66
|
|
|
3883
|
is_inner => ( ( $inf->{attrs}{join_type} || '' ) !~ /^left/i), |
|
|
|
|
100
|
|
|
|
|
|
185
|
|
|
|
|
|
|
rsrc => $self->related_source($rel), |
|
186
|
|
|
|
|
|
|
}; |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# FIME - need to use _resolve_cond here instead |
|
189
|
379
|
|
|
|
|
1925
|
my $cond = $inf->{cond}; |
|
190
|
|
|
|
|
|
|
|
|
191
|
379
|
50
|
66
|
|
|
4003
|
if ( |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
192
|
|
|
|
|
|
|
ref $cond eq 'HASH' |
|
193
|
|
|
|
|
|
|
and |
|
194
|
|
|
|
|
|
|
keys %$cond |
|
195
|
|
|
|
|
|
|
and |
|
196
|
378
|
|
|
378
|
|
3327
|
! defined first { $_ !~ /^foreign\./ } (keys %$cond) |
|
197
|
|
|
|
|
|
|
and |
|
198
|
378
|
|
|
378
|
|
1830
|
! defined first { $_ !~ /^self\./ } (values %$cond) |
|
199
|
|
|
|
|
|
|
) { |
|
200
|
378
|
|
|
|
|
1135
|
for my $f (keys %$cond) { |
|
201
|
378
|
|
|
|
|
948
|
my $s = $cond->{$f}; |
|
202
|
378
|
|
|
|
|
2947
|
$_ =~ s/^ (?: foreign | self ) \.//x for ($f, $s); |
|
203
|
378
|
|
|
|
|
2547
|
$relinfo->{$rel}{fk_map}{$s} = $f; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# inject non-left fk-bridges from *INNER-JOINED* children (if any) |
|
209
|
561
|
|
|
|
|
1867
|
for my $rel (grep { $relinfo->{$_}{is_inner} } keys %$relinfo) { |
|
|
379
|
|
|
|
|
1269
|
|
|
210
|
124
|
|
|
|
|
316
|
my $ri = $relinfo->{$rel}; |
|
211
|
124
|
|
|
|
|
236
|
for (keys %{$ri->{fk_map}} ) { |
|
|
124
|
|
|
|
|
407
|
|
|
212
|
|
|
|
|
|
|
# need to know source from *our* pov, hence $rel.col |
|
213
|
|
|
|
|
|
|
$my_cols->{$_} ||= { via_fk => "$rel.$ri->{fk_map}{$_}" } |
|
214
|
124
|
100
|
100
|
|
|
789
|
if defined $rel_cols->{$rel}{$ri->{fk_map}{$_}} # in fact selected |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
} |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# if the parent is already defined *AND* we have an inner reverse relationship |
|
219
|
|
|
|
|
|
|
# (i.e. do not exist without it) , assume all of its related FKs are selected |
|
220
|
|
|
|
|
|
|
# (even if they in fact are NOT in the select list). Keep a record of what we |
|
221
|
|
|
|
|
|
|
# assumed, and if any such phantom-column becomes part of our own collapser, |
|
222
|
|
|
|
|
|
|
# throw everything assumed-from-parent away and replace with the collapser of |
|
223
|
|
|
|
|
|
|
# the parent (whatever it may be) |
|
224
|
561
|
|
|
|
|
1088
|
my $assumed_from_parent; |
|
225
|
561
|
100
|
100
|
|
|
2710
|
if ( ! $args->{_parent_info}{underdefined} and ! $args->{_parent_info}{rev_rel_is_optional} ) { |
|
226
|
395
|
100
|
|
|
|
878
|
for my $col ( values %{$args->{_parent_info}{rel_condition} || {}} ) { |
|
|
395
|
|
|
|
|
1754
|
|
|
227
|
227
|
100
|
|
|
|
762
|
next if exists $my_cols->{$col}; |
|
228
|
54
|
|
|
|
|
201
|
$my_cols->{$col} = { via_collapse => $args->{_parent_info}{collapse_on_idcols} }; |
|
229
|
54
|
|
|
|
|
210
|
$assumed_from_parent->{columns}{$col}++; |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# get colinfo for everything |
|
234
|
561
|
100
|
|
|
|
1611
|
if ($my_cols) { |
|
235
|
541
|
|
|
|
|
2011
|
my $ci = $self->columns_info; |
|
236
|
541
|
|
|
|
|
3702
|
$my_cols->{$_}{colinfo} = $ci->{$_} for keys %$my_cols; |
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
|
|
239
|
561
|
|
|
|
|
1156
|
my $collapse_map; |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# first try to reuse the parent's collapser (i.e. reuse collapser over 1:1) |
|
242
|
|
|
|
|
|
|
# (makes for a leaner coderef later) |
|
243
|
561
|
50
|
|
|
|
1768
|
unless ($collapse_map->{-identifying_columns}) { |
|
244
|
|
|
|
|
|
|
$collapse_map->{-identifying_columns} = $args->{_parent_info}{collapse_on_idcols} |
|
245
|
561
|
100
|
|
|
|
1628
|
if $args->{_parent_info}{collapser_reusable}; |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# Still don't know how to collapse - try to resolve based on our columns (plus already inserted FK bridges) |
|
249
|
561
|
100
|
100
|
|
|
3019
|
if ( |
|
|
|
|
100
|
|
|
|
|
|
250
|
|
|
|
|
|
|
! $collapse_map->{-identifying_columns} |
|
251
|
|
|
|
|
|
|
and |
|
252
|
|
|
|
|
|
|
$my_cols |
|
253
|
|
|
|
|
|
|
and |
|
254
|
1541
|
|
|
|
|
4963
|
my $idset = $self->_identifying_column_set ({map { $_ => $my_cols->{$_}{colinfo} } keys %$my_cols}) |
|
255
|
|
|
|
|
|
|
) { |
|
256
|
|
|
|
|
|
|
# see if the resulting collapser relies on any implied columns, |
|
257
|
|
|
|
|
|
|
# and fix stuff up if this is the case |
|
258
|
423
|
|
|
|
|
1032
|
my @reduced_set = grep { ! $assumed_from_parent->{columns}{$_} } @$idset; |
|
|
526
|
|
|
|
|
2142
|
|
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
$collapse_map->{-identifying_columns} = [ __unique_numlist( |
|
261
|
423
|
100
|
|
|
|
1840
|
@{ $args->{_parent_info}{collapse_on_idcols}||[] }, |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
(map |
|
264
|
|
|
|
|
|
|
{ |
|
265
|
423
|
|
|
|
|
860
|
my $fqc = join ('.', |
|
266
|
496
|
|
|
|
|
2904
|
@{$args->{_rel_chain}}[1 .. $#{$args->{_rel_chain}}], |
|
|
496
|
|
|
|
|
1143
|
|
|
267
|
496
|
|
66
|
|
|
1023
|
( $my_cols->{$_}{via_fk} || $_ ), |
|
268
|
|
|
|
|
|
|
); |
|
269
|
|
|
|
|
|
|
|
|
270
|
496
|
|
|
|
|
2063
|
$common_args->{_as_fq_idx}->{$fqc}; |
|
271
|
|
|
|
|
|
|
} |
|
272
|
|
|
|
|
|
|
@reduced_set |
|
273
|
|
|
|
|
|
|
), |
|
274
|
|
|
|
|
|
|
)]; |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Stil don't know how to collapse - keep descending down 1:1 chains - if |
|
278
|
|
|
|
|
|
|
# a related non-LEFT 1:1 is resolvable - its condition will collapse us |
|
279
|
|
|
|
|
|
|
# too |
|
280
|
561
|
100
|
|
|
|
2585
|
unless ($collapse_map->{-identifying_columns}) { |
|
281
|
42
|
|
|
|
|
96
|
my @candidates; |
|
282
|
|
|
|
|
|
|
|
|
283
|
42
|
|
|
|
|
120
|
for my $rel (keys %$relinfo) { |
|
284
|
53
|
100
|
100
|
|
|
300
|
next unless ($relinfo->{$rel}{is_single} && $relinfo->{$rel}{is_inner}); |
|
285
|
|
|
|
|
|
|
|
|
286
|
28
|
50
|
|
|
|
74
|
if ( my $rel_collapse = $relinfo->{$rel}{rsrc}->_resolve_collapse ({ |
|
287
|
|
|
|
|
|
|
as => $rel_cols->{$rel}, |
|
288
|
28
|
|
|
|
|
258
|
_rel_chain => [ @{$args->{_rel_chain}}, $rel ], |
|
289
|
|
|
|
|
|
|
_parent_info => { underdefined => 1 }, |
|
290
|
|
|
|
|
|
|
}, $common_args)) { |
|
291
|
28
|
|
|
|
|
307
|
push @candidates, $rel_collapse->{-identifying_columns}; |
|
292
|
|
|
|
|
|
|
} |
|
293
|
|
|
|
|
|
|
} |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# get the set with least amount of columns |
|
296
|
|
|
|
|
|
|
# FIXME - maybe need to implement a data type order as well (i.e. prefer several ints |
|
297
|
|
|
|
|
|
|
# to a single varchar) |
|
298
|
42
|
100
|
|
|
|
142
|
if (@candidates) { |
|
299
|
28
|
|
|
|
|
83
|
($collapse_map->{-identifying_columns}) = sort { scalar @$a <=> scalar @$b } (@candidates); |
|
|
1
|
|
|
|
|
25
|
|
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
} |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# Stil don't know how to collapse, and we are the root node. Last ditch |
|
304
|
|
|
|
|
|
|
# effort in case we are *NOT* premultiplied. |
|
305
|
|
|
|
|
|
|
# Run through *each multi* all the way down, left or not, and all |
|
306
|
|
|
|
|
|
|
# *left* singles (a single may become a multi underneath) . When everything |
|
307
|
|
|
|
|
|
|
# gets back see if all the rels link to us definitively. If this is the |
|
308
|
|
|
|
|
|
|
# case we are good - either one of them will define us, or if all are NULLs |
|
309
|
|
|
|
|
|
|
# we know we are "unique" due to the "non-premultiplied" check |
|
310
|
561
|
50
|
66
|
|
|
2066
|
if ( |
|
|
|
|
66
|
|
|
|
|
|
311
|
|
|
|
|
|
|
! $collapse_map->{-identifying_columns} |
|
312
|
|
|
|
|
|
|
and |
|
313
|
|
|
|
|
|
|
! $args->{premultiplied} |
|
314
|
|
|
|
|
|
|
and |
|
315
|
|
|
|
|
|
|
$args->{_is_top_level} |
|
316
|
|
|
|
|
|
|
) { |
|
317
|
15
|
|
|
|
|
40
|
my (@collapse_sets, $uncollapsible_chain); |
|
318
|
|
|
|
|
|
|
|
|
319
|
15
|
|
|
|
|
78
|
for my $rel (keys %$relinfo) { |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# we already looked at these higher up |
|
322
|
23
|
50
|
66
|
|
|
93
|
next if ($relinfo->{$rel}{is_single} && $relinfo->{$rel}{is_inner}); |
|
323
|
|
|
|
|
|
|
|
|
324
|
23
|
50
|
|
|
|
62
|
if (my $clps = $relinfo->{$rel}{rsrc}->_resolve_collapse ({ |
|
325
|
|
|
|
|
|
|
as => $rel_cols->{$rel}, |
|
326
|
23
|
|
|
|
|
433
|
_rel_chain => [ @{$args->{_rel_chain}}, $rel ], |
|
327
|
|
|
|
|
|
|
_parent_info => { underdefined => 1 }, |
|
328
|
|
|
|
|
|
|
}, $common_args) ) { |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# for singles use the idcols wholesale (either there or not) |
|
331
|
23
|
100
|
|
|
|
99
|
if ($relinfo->{$rel}{is_single}) { |
|
|
|
50
|
|
|
|
|
|
|
332
|
9
|
|
|
|
|
51
|
push @collapse_sets, $clps->{-identifying_columns}; |
|
333
|
|
|
|
|
|
|
} |
|
334
|
|
|
|
|
|
|
elsif (! $relinfo->{$rel}{fk_map}) { |
|
335
|
1
|
|
|
|
|
28
|
$uncollapsible_chain = 1; |
|
336
|
1
|
|
|
|
|
5
|
last; |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
else { |
|
339
|
15
|
|
|
|
|
32
|
my $defined_cols_parent_side; |
|
340
|
|
|
|
|
|
|
|
|
341
|
15
|
|
|
|
|
65
|
for my $fq_col ( grep { /^$rel\.[^\.]+$/ } keys %{$args->{as}} ) { |
|
|
96
|
|
|
|
|
585
|
|
|
|
15
|
|
|
|
|
59
|
|
|
342
|
39
|
|
|
|
|
494
|
my ($col) = $fq_col =~ /([^\.]+)$/; |
|
343
|
|
|
|
|
|
|
|
|
344
|
39
|
|
|
|
|
81
|
$defined_cols_parent_side->{$_} = $args->{as}{$fq_col} for grep |
|
345
|
39
|
|
|
|
|
176
|
{ $relinfo->{$rel}{fk_map}{$_} eq $col } |
|
346
|
39
|
|
|
|
|
127
|
keys %{$relinfo->{$rel}{fk_map}} |
|
347
|
|
|
|
|
|
|
; |
|
348
|
|
|
|
|
|
|
} |
|
349
|
|
|
|
|
|
|
|
|
350
|
15
|
50
|
|
|
|
106
|
if (my $set = $self->_identifying_column_set([ keys %$defined_cols_parent_side ]) ) { |
|
351
|
15
|
|
|
|
|
63
|
push @collapse_sets, [ sort map { $defined_cols_parent_side->{$_} } @$set ]; |
|
|
15
|
|
|
|
|
168
|
|
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
else { |
|
354
|
1
|
|
|
|
|
5
|
$uncollapsible_chain = 1; |
|
355
|
1
|
|
|
|
|
3
|
last; |
|
356
|
|
|
|
|
|
|
} |
|
357
|
|
|
|
|
|
|
} |
|
358
|
|
|
|
|
|
|
} |
|
359
|
|
|
|
|
|
|
else { |
|
360
|
1
|
|
|
|
|
368
|
$uncollapsible_chain = 1; |
|
361
|
1
|
|
|
|
|
8
|
last; |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
|
|
365
|
15
|
50
|
|
|
|
58
|
unless ($uncollapsible_chain) { |
|
366
|
|
|
|
|
|
|
# if we got here - we are good to go, but the construction is tricky |
|
367
|
|
|
|
|
|
|
# since our children will want to include our collapse criteria - we |
|
368
|
|
|
|
|
|
|
# don't give them anything (safe, since they are all collapsible on their own) |
|
369
|
|
|
|
|
|
|
# in addition we record the individual collapse possibilities |
|
370
|
|
|
|
|
|
|
# of all left children node collapsers, and merge them in the rowparser |
|
371
|
|
|
|
|
|
|
# coderef later |
|
372
|
15
|
|
|
|
|
64
|
$collapse_map->{-identifying_columns} = []; |
|
373
|
|
|
|
|
|
|
$collapse_map->{-identifying_columns_variants} = [ sort { |
|
374
|
15
|
0
|
|
|
|
53
|
(scalar @$a) <=> (scalar @$b) or max(@$a) <=> max(@$b) |
|
|
9
|
|
|
|
|
89
|
|
|
375
|
|
|
|
|
|
|
} @collapse_sets ]; |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
} |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# stop descending into children if we were called by a parent for first-pass |
|
380
|
|
|
|
|
|
|
# and don't despair if nothing was found (there may be other parallel branches |
|
381
|
|
|
|
|
|
|
# to dive into) |
|
382
|
561
|
100
|
|
|
|
1993
|
if ($args->{_parent_info}{underdefined}) { |
|
|
|
50
|
|
|
|
|
|
|
383
|
50
|
50
|
|
|
|
372
|
return $collapse_map->{-identifying_columns} ? $collapse_map : undef |
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
# nothing down the chain resolved - can't calculate a collapse-map |
|
386
|
|
|
|
|
|
|
elsif (! $collapse_map->{-identifying_columns}) { |
|
387
|
|
|
|
|
|
|
$self->throw_exception ( sprintf |
|
388
|
|
|
|
|
|
|
"Unable to calculate a definitive collapse column set for %s%s: fetch more unique non-nullable columns", |
|
389
|
|
|
|
|
|
|
$self->source_name, |
|
390
|
1
|
|
|
|
|
178
|
@{$args->{_rel_chain}} > 1 |
|
391
|
1
|
0
|
|
|
|
2
|
? sprintf (' (last member of the %s chain)', join ' -> ', @{$args->{_rel_chain}} ) |
|
|
1
|
|
|
|
|
7
|
|
|
392
|
|
|
|
|
|
|
: '' |
|
393
|
|
|
|
|
|
|
, |
|
394
|
|
|
|
|
|
|
); |
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# If we got that far - we are collapsable - GREAT! Now go down all children |
|
398
|
|
|
|
|
|
|
# a second time, and fill in the rest |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
$collapse_map->{-identifying_columns} = [ __unique_numlist( |
|
401
|
512
|
100
|
|
|
|
1775
|
@{ $args->{_parent_info}{collapse_on_idcols}||[] }, |
|
402
|
512
|
|
|
|
|
895
|
@{ $collapse_map->{-identifying_columns} }, |
|
|
512
|
|
|
|
|
1442
|
|
|
403
|
|
|
|
|
|
|
)]; |
|
404
|
|
|
|
|
|
|
|
|
405
|
512
|
|
|
|
|
1285
|
my @id_sets; |
|
406
|
512
|
|
|
|
|
1605
|
for my $rel (sort keys %$relinfo) { |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
$collapse_map->{$rel} = $relinfo->{$rel}{rsrc}->_resolve_collapse ({ |
|
409
|
1820
|
|
|
|
|
3603
|
as => { map { $_ => 1 } ( keys %{$rel_cols->{$rel}} ) }, |
|
|
344
|
|
|
|
|
1426
|
|
|
410
|
344
|
|
|
|
|
1104
|
_rel_chain => [ @{$args->{_rel_chain}}, $rel], |
|
411
|
|
|
|
|
|
|
_parent_info => { |
|
412
|
|
|
|
|
|
|
# shallow copy |
|
413
|
344
|
|
|
|
|
1801
|
collapse_on_idcols => [ @{$collapse_map->{-identifying_columns}} ], |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
rel_condition => $relinfo->{$rel}{fk_map}, |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
is_optional => ! $relinfo->{$rel}{is_inner}, |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
# if there is at least one *inner* reverse relationship which is HASH-based (equality only) |
|
420
|
|
|
|
|
|
|
# we can safely assume that the child can not exist without us |
|
421
|
|
|
|
|
|
|
rev_rel_is_optional => ( first |
|
422
|
430
|
50
|
100
|
430
|
|
7455
|
{ ref $_->{cond} eq 'HASH' and ($_->{attrs}{join_type}||'') !~ /^left/i } |
|
423
|
344
|
|
|
|
|
1930
|
values %{ $self->reverse_relationship_info($rel) }, |
|
424
|
|
|
|
|
|
|
) ? 0 : 1, |
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
# if this is a 1:1 our own collapser can be used as a collapse-map |
|
427
|
|
|
|
|
|
|
# (regardless of left or not) |
|
428
|
|
|
|
|
|
|
collapser_reusable => ( |
|
429
|
|
|
|
|
|
|
$relinfo->{$rel}{is_single} |
|
430
|
|
|
|
|
|
|
&& |
|
431
|
|
|
|
|
|
|
$relinfo->{$rel}{is_inner} |
|
432
|
|
|
|
|
|
|
&& |
|
433
|
344
|
100
|
66
|
|
|
890
|
@{$collapse_map->{-identifying_columns}} |
|
|
|
100
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
) ? 1 : 0, |
|
435
|
|
|
|
|
|
|
}, |
|
436
|
|
|
|
|
|
|
}, $common_args ); |
|
437
|
|
|
|
|
|
|
|
|
438
|
344
|
100
|
|
|
|
2704
|
$collapse_map->{$rel}{-is_single} = 1 if $relinfo->{$rel}{is_single}; |
|
439
|
344
|
100
|
50
|
|
|
1674
|
$collapse_map->{$rel}{-is_optional} ||= 1 unless $relinfo->{$rel}{is_inner}; |
|
440
|
|
|
|
|
|
|
} |
|
441
|
|
|
|
|
|
|
|
|
442
|
512
|
|
|
|
|
3246
|
return $collapse_map; |
|
443
|
|
|
|
|
|
|
} |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
# adding a dep on MoreUtils *just* for this is retarded |
|
446
|
|
|
|
|
|
|
sub __unique_numlist { |
|
447
|
934
|
|
|
934
|
|
1444
|
sort { $a <=> $b } keys %{ {map { $_ => 1 } @_ }} |
|
|
1132
|
|
|
|
|
4133
|
|
|
|
934
|
|
|
|
|
1707
|
|
|
|
2283
|
|
|
|
|
8048
|
|
|
448
|
|
|
|
|
|
|
} |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
1; |