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