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