File Coverage

blib/lib/SQLite/More.pm
Criterion Covered Total %
statement 174 200 87.0
branch 35 62 56.4
condition 22 39 56.4
subroutine 55 65 84.6
pod 1 14 7.1
total 287 380 75.5


line stmt bran cond sub pod time code
1             package SQLite::More;
2             our $VERSION = '0.10';
3 1     1   60176 use 5.008008;
  1         4  
  1         39  
4 1     1   4 use strict;
  1         2  
  1         30  
5 1     1   5 use warnings;
  1         6  
  1         108  
6             require Exporter;
7             our @ISA = qw(Exporter);
8             our %EXPORT_TAGS = ( 'all' => [ qw(nvl decode random min max sum avg geomavg stddev median percentile distance) ] );
9             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
10             our @EXPORT = qw(sqlite_more);
11 1     1   2592 use DBD::SQLite 1.27; #minimum with $dbh->sqlite_create_function
  1         20025  
  1         36  
12 1     1   9 use DBI 1.609; #minimum with $dbh->sqlite_create_function
  1         20  
  1         48  
13 1     1   6 use Digest::MD5;
  1         2  
  1         46  
14 1     1   5 use Carp;
  1         3  
  1         1253  
15              
16             sub sqlite_more
17             {
18 1     1 0 7707 my $dbh=shift();
19            
20 1     1   12 $dbh->sqlite_create_function( 'nvl', 2, sub { nvl(@_) } );
  1         70  
21 1     24   9 $dbh->sqlite_create_function( 'decode', -1, sub { decode(@_) } );
  24         418  
22             # $dbh->sqlite_create_function( 'sysdate', 0, sub { sysdate() } ); #hm
23 1     1   7 $dbh->sqlite_create_function( 'upper', 1, sub { uc($_[0]) } );
  1         574  
24 1     1   6 $dbh->sqlite_create_function( 'lower', 1, sub { lc($_[0]) } );
  1         106  
25 1     3   7 $dbh->sqlite_create_function( 'least', -1, sub { min(@_) } );
  3         428  
26 1     3   10 $dbh->sqlite_create_function( 'greatest', -1, sub { max(@_) } );
  3         324  
27 1     1   9 $dbh->sqlite_create_function( 'md5', 1, sub { Digest::MD5::md5(@_) } );
  1         93  
28 1     3   7 $dbh->sqlite_create_function( 'md5_hex', 1, sub { Digest::MD5::md5_hex(@_) } );
  3         354  
29 1     1200   7 $dbh->sqlite_create_function( 'random', 2, sub { random(@_) } );
  1200         8859  
30 1     2   6 $dbh->sqlite_create_function( 'sprintf', -1, sub { sprintf(shift(),@_) } );
  2         30  
31 1     1   17 $dbh->sqlite_create_function( 'time', 0, sub { time() } );
  1         63  
32              
33 1     1   19 $dbh->sqlite_create_function( 'sqrt', 1, sub { sqrt(shift) } );
  1         416  
34 1     3   6 $dbh->sqlite_create_function( 'power', 2, sub { shift() ** shift() } );
  3         1183  
35 1     0   6 $dbh->sqlite_create_function( 'ln', 1, sub { log(shift) } ); #2.71
  0         0  
36 1     0   5 $dbh->sqlite_create_function( 'log', 1, sub { log(shift) } ); #2.71
  0         0  
37 1     0   5 $dbh->sqlite_create_function( 'loge', 1, sub { log(shift) } ); #2.71
  0         0  
38 1     1   6 $dbh->sqlite_create_function( 'log10', 1, sub { log(shift)/log(10) } );
  1         409  
39 1     2   6 $dbh->sqlite_create_function( 'log2', 1, sub { log(shift)/log(2) } );
  2         19  
40 1     1   5 $dbh->sqlite_create_function( 'pi', 0, sub { 3.14159265358979323846264338327950288419716939937510 } );
  1         60  
41 1     1   6 $dbh->sqlite_create_function( 'sin', 1, sub { sin(shift) } );
  1         1625  
42 1     1   5 $dbh->sqlite_create_function( 'cos', 1, sub { cos(shift) } );
  1         472  
43 1     1   5 $dbh->sqlite_create_function( 'tan', 1, sub { sin($_[0])/cos($_[0]) } );
  1         420  
44 1     1   7 $dbh->sqlite_create_function( 'atan2', 2, sub { atan2(shift,shift) } );
  1         398  
45 1     10   33 $dbh->sqlite_create_function( 'perlhash', -1, sub { perlhash(@_) } );
  10         807  
46            
47 1     1   6 $dbh->sqlite_create_function( 'distance', 4, sub { distance(@_) } );
  1         326  
48              
49             #$dbh->sqlite_create_function( 'sum', -1, sub { sum(@_) } );
50 1         6 $dbh->sqlite_create_aggregate( "variance", 1, 'SQLite::More::variance' );
51 1         4 $dbh->sqlite_create_aggregate( "stddev", 1, 'SQLite::More::stddev' );
52 1         34 $dbh->sqlite_create_aggregate( "median", 1, 'SQLite::More::median' );
53 1         7 $dbh->sqlite_create_aggregate( "percentile", 2, 'SQLite::More::percentile' );
54              
55             }
56              
57             sub nvl #copied from Acme::Tools 1.14
58             {
59 1 50 33 1 0 13 return $_[0] if defined $_[0] and length($_[0]) or @_==1;
      33        
60 1 50       10 return $_[1] if @_==2;
61 0 0       0 return nvl(@_[1..$#_]) if @_>2;
62 0         0 return undef;
63             }
64             sub decode #copied from Acme::Tools 1.14
65             {
66 24 50   24 0 54 croak "Must have a mimimum of two arguments" if @_<2;
67 24         29 my $uttrykk=shift;
68 24 100 100     73 if(defined$uttrykk){ shift eq $uttrykk and return shift or shift for 1..@_/2 }
  22   33     163  
69 2   50     17 else { not defined shift and return shift or shift for 1..@_/2 }
      33        
70 18         106 return shift;
71             }
72             sub random #copied from Acme::Tools 1.14
73             {
74 1200     1200 0 1315 my($from,$to)=@_;
75 1200 50       2292 if(ref($from) eq 'ARRAY'){
76 0         0 return $$from[random($#$from)];
77             }
78 1200 50       2036 ($from,$to)=(0,$from) if @_==1;
79 1200 50       1929 ($from,$to)=($to,$from) if $from>$to;
80 1200         5892 return int($from+rand(1+$to-$from));
81             }
82             sub min #copied from Acme::Tools 1.14
83             {
84 3     3 0 5 my $min;
85 3 100 100     8 for(@_){ $min=$_ if defined($_) and !defined($min) || $_<$min }
  107   66     333  
86 3         41 $min;
87             }
88             sub max #copied from Acme::Tools 1.14
89             {
90 3     3 0 3 my $max;
91 3 100 100     7 for(@_){ $max=$_ if defined($_) and !defined($max) || $_>$max }
  7   66     51  
92 3         38 $max;
93             }
94             sub sum #copied from Acme::Tools 1.14
95             {
96 1     1 0 7 my $sum; no warnings;
  1     0   1  
  1         100  
  0         0  
97 0         0 $sum+=$_ for @_;
98 0         0 $sum;
99             }
100             sub avg #copied from Acme::Tools 1.14
101             {
102 0     0 0 0 my $sum=0;
103 1     1   5 no warnings;
  1         8  
  1         195  
104 0         0 $sum+=$_ for @_;
105 0 0       0 return $sum/@_ if @_>0;
106 0         0 return undef;
107             }
108             sub geomavg #copied from Acme::Tools 1.14
109 0     0 0 0 { exp(avg(map log($_),@_)) }
110             sub stddev #copied from Acme::Tools 1.14
111             {
112 0     0 0 0 my $sumx2; $sumx2+=$_*$_ for @_;
  0         0  
113 0         0 my $sumx; $sumx+=$_ for @_;
  0         0  
114 0         0 sqrt( (@_*$sumx2-$sumx*$sumx)/(@_*(@_-1)) );
115             }
116             sub median #copied from Acme::Tools 1.14
117             {
118 1     1   6 no warnings;
  1         3  
  1         669  
119 1     1 0 6 my @list = sort {$a<=>$b} @_;
  28         25  
120 1         2 my $n=@list;
121 1 50       21 $n%2
122             ? $list[($n-1)/2]
123             : ($list[$n/2-1] + $list[$n/2])/2;
124             }
125             sub percentile #copied from Acme::Tools 1.14
126             {
127 2     2 0 3 my(@p,@t,@ret);
128 2 50       8 if(ref($_[0]) eq 'ARRAY'){ @p=@{shift()} }
  0 50       0  
  0         0  
129 2         5 elsif(not ref($_[0])) { @p=(shift()) }
  0         0  
130             else{croak()}
131 2         6 @t=@_;
132 2 50       7 return if not @p;
133 2 50       5 croak if not @t;
134 2         6 @t=sort{$a<=>$b}@t;
  56         51  
135 2 50       7 push@t,$t[0] if @t==1;
136 2         5 for(@p){
137 2 50 33     11 croak if $_<0 or $_>100;
138 2         8 my $i=(@t+1)*$_/100-1;
139 2 50       30 push@ret,
    50          
    50          
140             $i<0 ? $t[0]+($t[1]-$t[0])*$i:
141             $i>$#t ? $t[-1]+($t[-1]-$t[-2])*($i-$#t):
142             $i==int($i)? $t[$i]:
143             $t[$i]*(int($i+1)-$i) + $t[$i+1]*($i-int($i));
144             }
145 2 50       63 return @p==1 ? $ret[0] : @ret;
146             }
147             our $Distance_factor=3.141592653589793238462643383279502884197169399375105820974944592307816406286 / 180;
148             sub distance #copied from Acme::Tools 1.14
149             {
150 1     1 0 5 my($lat1,$lon1,$lat2,$lon2)=map $Distance_factor*$_, @_;
151 1         15 my $a= sin(($lat2-$lat1)/2)**2
152             + sin(($lon2-$lon1)/2)**2 * cos($lat1) * cos($lat2);
153 1 50       4 my $sqrt_a =sqrt($a); $sqrt_a =1 if $sqrt_a >1;
  1         7  
154 1 50       2 my $sqrt_1ma=sqrt(1-$a); $sqrt_1ma=1 if $sqrt_1ma>1;
  1         4  
155 1         16 my $c=2*atan2($sqrt_a,$sqrt_1ma);
156 1         68 my($Re,$Rp)=( 6378137.0, 6356752.3 ); #earth equatorial and polar radius
157 1         5 my $R=$Re-($Re-$Rp)*sin(abs($lat1+$lat2)/2); #approx
158 1         10 return $c*$R;
159             }
160             sub perlhash
161             {
162 10     10 1 52 my($hashname,$key,$val)=@_;
163 10 100 100     76 $hashname=((caller(3))[0]||'main').'::'.$hashname if $hashname!~/::/;
164 10 50       59 die if not $hashname=~/^(\w+::)*\w+$/; #noedv?
165 1     1   6 no strict 'refs';
  1         2  
  1         586  
166 10         30 my $r=$$hashname{$key};
167 10 100       25 $$hashname{$key}=$val if @_>=3;
168 10         129 return $r;
169             }
170              
171              
172             1;
173             package SQLite::More::variance;
174 1     1   103 sub new {bless [],shift}sub step{push @{$_[0]},$_[1]}
  12     12   14  
  12         60  
175             sub finalize {
176 1     1   3 my $self = shift;
177 1         2 my $n = @$self;
178 1 50 33     10 return undef if not defined $n or $n < 2; #need at least 2
179 1         3 my $avg = 0;
180 1         5 $avg += $_ for @$self;
181 1         3 $avg /= $n;
182 1         2 my $sigma = 0;
183 1         9 $sigma += ($_-$avg)**2 for @$self;
184 1         3 $sigma /= $n - 1;
185 1         17 return $sigma;
186             }
187             1;
188              
189             package SQLite::More::stddev;
190 3     3   1189 sub new {bless {n=>undef,sumx=>undef,sumx2=>undef},shift}
191             sub step{
192 36     36   47 my($self,$value)=@_;
193 36         47 $$self{'n'}++;
194 36         41 $$self{'sumx'}+=$value;
195 36         174 $$self{'sumx2'}+=$value**2;
196             }
197             sub finalize {
198 3     3   7 my $self=shift;
199 3         5 my $n=$$self{'n'};
200 3 50 33     29 return undef if not defined $n or $n < 2; #need at least 2
201 3         41 return sqrt( ($n*$$self{'sumx2'}-$$self{'sumx'}**2)/$n/($n-1) );
202             }
203             1;
204              
205             package SQLite::More::median;
206 1     1   390 sub new {bless [],shift}sub step{push @{$_[0]},$_[1]}
  12     12   13  
  12         49  
207 1     1   2 sub finalize {SQLite::More::median(@{$_[0]})}
  1         11  
208             1;
209              
210             package SQLite::More::percentile;
211 2     2   160 sub new {bless [],shift}
212             sub step{
213 24     24   32 my($self,$percentile,$value)=@_;
214 24 100       55 push @$self,$percentile if not @$self;
215 24 50       49 die if $$self[0] != $percentile;
216 24         129 push @$self,$value;
217             }
218             sub finalize {
219             #$_[0][0]*=100 if $_[0][0]<2; #hm
220 2     2   4 SQLite::More::percentile(@{$_[0]})
  2         8  
221             }
222              
223             package SQLite::More::correlation;
224 0     0     sub new {bless [],shift}sub step{push @{$_[0]},$_[1]}
  0     0      
  0            
225 0     0     sub finalize {
226             }
227             1;
228              
229             __END__