File Coverage

blib/lib/SQL/Abstract/Plugin/TableAlias.pm
Criterion Covered Total %
statement 167 173 96.5
branch 51 66 77.2
condition 36 60 60.0
subroutine 16 16 100.0
pod 0 1 0.0
total 270 316 85.4


line stmt bran cond sub pod time code
1             package SQL::Abstract::Plugin::TableAlias;
2 3     3   59933 use strict; use warnings; our $VERSION = '0.02';
  3     3   7  
  3         75  
  3         15  
  3         6  
  3         166  
3 3     3   1362 use Moo;
  3         28968  
  3         13  
4              
5             with 'SQL::Abstract::Role::Plugin';
6              
7             sub register_extensions {
8 2     2 0 1510 my ($self, $sqla) = @_;
9 2         18 $sqla->plugin('+ExtraClauses');
10             $sqla->wrap_expander(select => sub {
11 2     2   76 $self->cb('_alias_select', $_[0]);
12 2         15344 });
13             }
14              
15             sub _alias_select {
16 31     31   175905 my ($self, $orig, $select, $args) = @_;
17 31 50 33     288 $args = $self->_alias_from_array($args) if (ref $args eq 'HASH' && ref $args->{from} eq 'ARRAY');
18 31         184 return $self->sqla->$orig($select, $args);
19             }
20              
21             sub _alias_from_array {
22 31     31   84 my ($self, $args) = @_;
23              
24 31   100     162 $args->{talias} ||= [];
25              
26 31         78 my ($i, @map, %columns) = 0;
27 31         54 for my $from (@{ $args->{from} }) {
  31         88  
28 96   100     252 my $ref = ref $from || "";
29 96 100 66     404 if ( $ref eq 'HASH' ) {
    100          
    100          
30 26 50       60 if ($from->{to}) {
31 26 100 33     100 $from->{as} ||= scalar @{$args->{talias}} ? shift(@{$args->{talias}}) : ref $from->{to} ? $from->{to}->{-ident}->[0] : $from->{to};
  26 100       118  
  13         54  
32 26         59 push @map, $from->{as};
33 26 50       69 if ($from->{on}) {
34 26 100       71 if ($from->{on}->{-op}) {
35 2 50       5 if (scalar @{$from->{on}->{-op}->[1]->{-ident}} == 1) {
  2         10  
36 2         5 unshift @{$from->{on}{-op}[1]{-ident}}, $map[-2];
  2         9  
37             }
38 2 50       4 if (scalar @{$from->{on}->{-op}->[2]->{-ident}} == 1) {
  2         8  
39 2         5 unshift @{$from->{on}{-op}[2]{-ident}}, $map[-1];
  2         8  
40             }
41             } else {
42 24         49 for my $on (keys %{$from->{on}}) {
  24         88  
43 24 50       67 if (ref $from->{on}->{$on}) {
44 24         39 for my $oo (keys %{$from->{on}->{$on}}) {
  24         91  
45 24         173 $from->{on}->{$on}->{$oo} = sprintf("%s.%s", $map[-1], $from->{on}->{$on}->{$oo});
46             }
47             }
48 24         112 $from->{on}->{sprintf("%s.%s", $map[-2], $on)} = delete $from->{on}->{$on};
49             }
50             }
51             }
52             } else {
53             push @map, $from->{$_}->{-as} ||= shift(@{$args->{talias}}) || $_
54 0   0     0 for ( sort keys %{ $from } );
  0   0     0  
55             }
56             } elsif ($ref eq 'ARRAY') {
57 3 50       10 if ($from->[1] eq 'as') {
58 0         0 push @map, $from->[2];
59             } else {
60 3   66     8 push @map, shift @{$args->{talias}} || $from->[0];
61 3         7 splice @{$from}, 1, 0, 'as', $map[-1];
  3         15  
62             }
63 3         7 for my $key ( keys %{ $from->[-1] } ) {
  3         23  
64 3         28 $from->[-1]->{_valid_column($key, $map[-2], {})} = _valid_column(delete $from->[-1]->{$key}, $map[-1], {});
65             }
66             } elsif (!$ref && $from !~ m/^-/) {
67 38   66     65 push @map, shift @{$args->{talias}} || $from;
68 38         69 splice @{$args->{from}}, $i, 1, { $from => { 'as' => $map[-1] } };
  38         170  
69             }
70 96         179 $i++;
71             }
72              
73             ($args, %columns) = $self->_alias_select_array($args, \@map)
74 31 50 50     197 if ((ref($args->{select}) || "") eq 'ARRAY');
75            
76 31         95 my $where = ref $args->{where};
77 31 100 66     139 $where eq 'HASH'
78             ? $self->_alias_where_hash($args, $map[0], \%columns)
79             : $where eq 'ARRAY' && $self->_alias_where_array($args, $map[0], \%columns);
80              
81 31         60 my $order_by = ref $args->{order_by};
82             $order_by eq 'HASH'
83             ? $self->_alias_order_by_hash($args, $map[0], \%columns)
84             : $order_by eq 'ARRAY'
85             ? $self->_alias_order_by_array($args, $map[0], \%columns)
86 31 100 66     207 : defined $args->{order_by} && ! ref $order_by && $self->_alias_order_by_string($args, $map[0], \%columns);
    100          
87              
88 31         64 my $group_by = ref $args->{group_by};
89 31 100 66     114 $group_by eq 'ARRAY'
90             ? $self->_alias_group_by_array($args, $map[0], \%columns)
91             : $group_by eq 'HASH' && $self->_alias_group_by_hash($args, $map[0], \%columns);
92              
93 31         85 return $args;
94             }
95              
96             sub _alias_select_array {
97 31     31   125 my ($self, $args, $map) = @_;
98 31         75 my ($i, $last_array, @select, %columns) = -1;
99 31         47 for my $sel ( @{ $args->{select} } ) {
  31         87  
100 122         197 my $ref = ref $sel;
101 122 100       326 if ( $ref eq 'ARRAY' ) {
    100          
    50          
102 33         57 $i++;
103 33         73 for (my $l = 0; $l < scalar @{$sel}; $l++) {
  77         159  
104 44 100 100     150 if (ref($sel->[$l]) || "" eq "HASH") {
105 1         2 for my $key ( keys %{ $sel->[$l] } ) {
  1         4  
106 1         6 $sel->[$l]{_valid_column($key, $map->[$i], {})} = delete $sel->[$l]{$key};
107 1         5 $columns{$key} = $map->[$i];
108             }
109 1         2 push @select, $sel->[$l];
110             } else {
111 43         103 $columns{$sel->[$l]} = $map->[$i];
112 43         139 push @select, sprintf("%s.%s", $map->[$i], $sel->[$l]);
113             }
114             }
115 33         80 $last_array = 1;
116             } elsif ( $ref eq 'HASH' ) {
117 2 50 33     10 $i++ if $i < 0 || $last_array && do { $last_array = 0; 1; };
  0   66     0  
  0         0  
118 2         4 for my $key ( keys %{ $sel } ) {
  2         5  
119 2         8 $sel->{_valid_column($key, $map->[$i], {})} = delete $sel->{$key};
120 2         7 $columns{$key} = $map->[$i];
121             }
122 2         4 push @select, $sel;
123             } elsif (! $ref) {
124 87 50 66     229 $i++ if $i < 0 || $last_array && do { $last_array = 0; 1; };
  4   100     7  
  4         19  
125 87         192 $columns{$sel} = $map->[$i];
126 87         244 push @select, sprintf("%s.%s", $map->[$i], $sel);
127             }
128             }
129 31         59 $args->{select} = \@select;
130 31         168 return ($args, %columns);
131             }
132              
133             sub _alias_where_hash {
134 17     17   42 my ($self, $args, $default, $columns) = @_;
135 17         30 my %where;
136 17         43 for my $w (keys %{ $args->{where} }) {
  17         49  
137 39 50 33     102 if (ref $args->{$w} eq 'HASH' && $args->{$w}->{-alias}) {
138 0         0 $where{sprintf("%s.%s", delete $args->{where}->{$w}->{-alias}, $w)} = $args->{where}->{$w};
139             } else {
140 39         87 $where{_valid_column($w, $default, $columns)} = $args->{where}->{$w};
141             }
142             }
143 17         33 $args->{where} = \%where;
144 17         43 return $args;
145             }
146              
147             sub _alias_where_array {
148 6     6   19 my ($self, $args, $default, $columns) = @_;
149 6 100       14 my $list = grep { $_ % 2 > 0 && $args->{where}->[$_] =~ m/-(and|or)/ } 0 .. scalar @{ $args->{where} };
  22         85  
  6         22  
150 6 50       18 return $self->_alias_where_list($args, $default, $columns) if $list;
151 6         12 for my $where (@{ $args->{where} }) {
  6         15  
152 16   100     42 my $ref = ref $where || "";
153 16 100       34 if ( $ref eq 'HASH' ) {
154 12         35 my $update = $self->_alias_where_hash({ where => $where }, $default, $columns);
155 12         14 %{$where} = %{$update->{where}};
  12         42  
  12         30  
156             }
157             }
158 6         10 return $args;
159             }
160              
161             sub _alias_order_by_hash {
162 9     9   22 my ($self, $args, $default, $columns) = @_;
163 9         14 my %order_by;
164 9         12 for my $w (keys %{ $args->{order_by} }) {
  9         24  
165 9         19 my $ref = ref $args->{order_by}->{$w};
166 9 100       32 if ($ref eq 'ARRAY') {
    50          
167 5         39 my @order;
168 5         8 for my $o ( @{ $args->{order_by}->{$w} } ) {
  5         15  
169 10         18 push @order, _valid_column($o, $default, $columns);
170             }
171 5         15 $order_by{$w} = \@order;
172             } elsif ( ! $ref ) {
173 4         12 $order_by{$w} = _valid_column($args->{order_by}{$w}, $default, $columns);
174             }
175             }
176 9         20 $args->{order_by} = \%order_by;
177 9         16 return $args;
178             }
179              
180             sub _alias_order_by_array {
181 6     6   17 my ($self, $args, $default, $columns) = @_;
182 6         11 my $i = 0;
183 6         16 for my $w ( @{ $args->{order_by} }) {
  6         16  
184 16   100     47 my $ref = ref $w || "";
185 16 100       28 if ($ref eq 'HASH') {
186 8         25 my $new = $self->_alias_order_by_hash({ order_by => $w }, $default, $columns);
187 8         13 %{$w} = %{$new->{order_by}};
  8         21  
  8         23  
188             } else {
189 8         24 $args->{order_by}->[$i] = _valid_column($w, $default, $columns);
190             }
191 16         33 $i++;
192             }
193 6         13 return $args;
194             }
195              
196             sub _alias_order_by_string {
197 12     12   28 my ($self, $args, $default, $columns) = @_;
198 12         34 $args->{order_by} = _valid_column($args->{order_by}, $default, $columns);
199             }
200              
201             sub _alias_group_by_array {
202 5     5   13 my ($self, $args, $default, $columns) = @_;
203 5         10 my @group_by;
204 5         47 for my $group (@{ $args->{group_by} }) {
  5         12  
205 7         19 push @group_by, _valid_column($group, $default, $columns);
206             }
207 5         12 $args->{group_by} = \@group_by;
208 5         9 return $args;
209             }
210              
211             sub _alias_group_by_hash {
212 2     2   6 my ($self, $args, $default, $columns) = @_;
213 2         4 my @group_by = shift @{ $args->{group_by}->{-op} };
  2         25  
214 2         4 for my $group (@{ $args->{group_by}->{-op} }) {
  2         13  
215             $group->{-ident} = ref $group->{-ident} ? [map {
216 4         10 _valid_column($_, $default, $columns);
217 4 50       10 } @{$group->{-ident}}] : _valid_column($group->{-ident}, $default, $columns);
  4         9  
218 4         8 push @group_by, $group;
219             }
220 2         5 $args->{group_by}->{-op} = \@group_by;
221 2         4 return $args;
222             }
223              
224             sub _valid_column {
225 93     93   169 my ($column, $default, $columns) = @_;
226 93 100       243 return $column if ($column =~ m/[^.]+\W+/);
227 92   66     413 return sprintf( "%s.%s", ($columns->{$column} || $default), $column);
228             }
229              
230             1;
231              
232             __END__