File Coverage

blib/lib/SQL/OrderBy.pm
Criterion Covered Total %
statement 56 56 100.0
branch 39 44 88.6
condition 10 12 83.3
subroutine 8 8 100.0
pod 4 4 100.0
total 117 124 94.3


line stmt bran cond sub pod time code
1             # $Id: OrderBy.pm,v 1.5 2004/08/23 03:06:21 gene Exp $
2              
3             package SQL::OrderBy;
4             $VERSION = '0.09';
5 1     1   35106 use strict;
  1         2  
  1         35  
6 1     1   1561 use warnings;
  1         5  
  1         68  
7 1     1   6 use Carp;
  1         7  
  1         1066  
8              
9             # Transform an order by clause.
10             sub toggle_resort {
11 12     12 1 3738 my %args = @_;
12              
13             # Set the column name list and the directions.
14 12         32 my ($columns, $direction, $asc_desc) = get_columns(
15             %args,
16             name_direction => 1,
17             numeric_direction => 1,
18             );
19              
20             # Handle a selected column.
21 12 50       36 if (my $name = $args{selected}) {
22 12         20 ($name, $direction, $asc_desc) = _name_direction(
23             $name, $direction, $asc_desc
24             );
25              
26             # Toggle if the selected column was already the first one.
27 12 100 66     78 if ($columns && @$columns && $name eq $columns->[0]) {
      100        
28 2 50       7 $direction->{$name} = $direction->{$name} + 0 ? 0 : 1;
29             }
30              
31             # Remove the selected column name from its old position.
32 12         17 @$columns = grep { $_ ne $name } @$columns;
  30         71  
33             # And add the selected column name to the beginning.
34 12         25 unshift @$columns, $name;
35             }
36              
37             # Convert from numeric, if asked to.
38 12 50       40 %$direction = to_asc_desc ($direction, %args)
39             unless $args{numeric_direction};
40              
41             # Fetch our "name direction" array.
42 12         29 @$columns = col_dir_list ($columns, $direction);
43              
44             # Return the column ordering as an arrayref or string.
45 12 100       85 return wantarray ? @$columns : join ', ', @$columns;
46             }
47              
48             # Return the column names and directions as either hash/array
49             # references, or a column array, or an "order by" clause.
50             sub get_columns {
51 20     20 1 4550 my %args = @_;
52              
53             # Set the order array from the order_by argument.
54 20         23 my @order;
55 20 100       47 if (ref $args{order_by} eq 'ARRAY') {
56 5         7 @order = @{ $args{order_by} };
  5         12  
57             # warn "Empty order list provided." unless @order;
58             }
59             else {
60 15 100       30 if ($args{order_by}) {
61             # Strip off any unneeded SQL clauses.
62 12         61 $args{order_by} =~ s/^.*?\border by\s+(.*)$/$1/i;
63             # Split the order clause.
64 12         82 @order = split /\s*,\s*/, $args{order_by};
65             }
66             else {
67 3         6 @order = ();
68             # warn "No statement or clause provided.\n" unless $args{order_by};
69             }
70             }
71              
72             # Hold column names and directions.
73 20         24 my ($columns, $direction, $asc_desc);
74              
75             # Set the column array and direction hashes.
76 20         36 for (@order) {
77 48         84 (my $name, $direction, $asc_desc) = _name_direction(
78             $_, $direction, $asc_desc
79             );
80              
81             # Add the column to our columns array.
82 48         114 push @$columns, $name;
83             }
84              
85             # Make alpha directions if asked to.
86 20 100       57 %$direction = to_asc_desc ($asc_desc, %args)
87             unless $args{numeric_direction};
88              
89             # NOTE: name_direction only makes sense in an array context.
90 20 100       52 if ($args{name_direction}) {
91 14         27 $columns = [ $columns, $direction, $asc_desc ];
92             }
93             else {
94 6         12 @$columns = col_dir_list ($columns, $direction);
95             }
96              
97 20 100       99 return wantarray ? @$columns : join ', ', @$columns;
98             }
99              
100             # Return an array of column names with their respective directions
101             # concatinated. This is conditional concatination. ASC/DESC vs.
102             # 1/0 issues do not concern us here.
103             sub col_dir_list {
104 19     19 1 427 my ($columns, $direction) = @_;
105 49 100       180 return map {
106 19         26 $direction->{$_}
107             ? "$_ $direction->{$_}"
108             : $_
109             } @$columns;
110             }
111              
112             # Return alpha directions in place of numeric eqivalents.
113             sub to_asc_desc {
114 21     21 1 895 my $dir = shift;
115 21         40 my %args = @_;
116              
117             # Set default direction strings.
118 21 100       49 my ($asc, $desc) = $args{uc_direction}
119             ? ('ASC', 'DESC') : ('asc', 'desc');
120              
121             # Replace directions with "proper" values.
122 21         56 for (keys %$dir) {
123             # From numeric
124 55 100 66     297 if (defined $dir->{$_} && $dir->{$_} =~ /^\d+$/) {
125 40 100       143 $dir->{$_} = $dir->{$_}
    100          
126             ? $args{show_ascending} ? $asc : ''
127             : $desc;
128             }
129             # Use existing if present, ascend otherwise.
130             else {
131 15 50       54 $dir->{$_} = $dir->{$_}
    100          
    100          
    100          
132             ? lc ($dir->{$_}) eq 'desc'
133             ? $dir->{$_}
134             : $args{show_ascending} ? $dir->{$_} : ''
135             : $args{show_ascending} ? $asc : ''
136             }
137             }
138              
139 21         117 return %$dir;
140             }
141              
142             sub _name_direction {
143 60     60   74 my ($col, $direction, $asc_desc) = @_;
144              
145 60 50       311 if ($col =~ /^(.*?)(?:\s+(asc|desc))?$/i) {
146             # Use the direction provided; Ascend by default.
147 60         127 ($col, my $dir) = ($1, $2);
148             # Set the numeric directions.
149 60 100 100     229 $direction->{$col} = $dir && lc ($dir) eq 'desc' ? 0 : 1;
150             # Set the case sensitive alpha directions.
151 60 100       140 $asc_desc->{$col} = $dir ? $dir : '';
152             }
153              
154 60         178 return $col, $direction, $asc_desc;
155             }
156              
157             1;
158             __END__