File Coverage

blib/lib/Apache/Session/Browseable/DBI.pm
Criterion Covered Total %
statement 101 141 71.6
branch 27 58 46.5
condition 6 17 35.2
subroutine 11 15 73.3
pod 0 4 0.0
total 145 235 61.7


line stmt bran cond sub pod time code
1             package Apache::Session::Browseable::DBI;
2              
3 4     4   332218 use strict;
  4         9  
  4         171  
4              
5 4     4   33 use DBI;
  4         8  
  4         230  
6 4     4   696 use Apache::Session;
  4         2314  
  4         108  
7 4     4   2180 use Apache::Session::Browseable::_common;
  4         14  
  4         2655  
8              
9             our $VERSION = '1.3.9';
10             our @ISA = qw(Apache::Session Apache::Session::Browseable::_common);
11              
12             sub searchOn {
13 6     6 0 14111 my $class = shift;
14 6         24 my ( $args, $selectField, $value, @fields ) = @_;
15              
16             # Escape quotes
17 6         22 $selectField =~ s/'/''/g;
18 6 100       42 if ( $class->_fieldIsIndexed( $args, $selectField ) ) {
19 4         38 return $class->_query( $args, $selectField, $value,
20             { query => "$selectField=?", values => [$value] }, @fields );
21             }
22             else {
23 2         68 return $class->SUPER::searchOn(@_);
24             }
25             }
26              
27             sub searchOnExpr {
28 2     2 0 74 my $class = shift;
29 2         10 my ( $args, $selectField, $value, @fields ) = @_;
30              
31             # Escape quotes
32 2         5 $value =~ s/'/''/g;
33 2         3 $selectField =~ s/'/''/g;
34 2 100       10 if ( $class->_fieldIsIndexed( $args, $selectField ) ) {
35 1         4 $value =~ s/\*/%/g;
36 1         9 return $class->_query( $args, $selectField, $value,
37             { query => "$selectField like ?", values => [$value] }, @fields );
38             }
39             else {
40 1         15 return $class->SUPER::searchOnExpr(@_);
41             }
42             }
43              
44             sub _query {
45 5     5   16 my ( $class, $args, $selectField, $value, $query, @fields ) = @_;
46 5         12 my %res = ();
47             my $index =
48             ref( $args->{Index} )
49             ? $args->{Index}
50 5 50       25 : [ split /\s+/, $args->{Index} ];
51              
52 5         25 my $dbh = $class->_classDbh($args);
53             my $table_name = $args->{TableName}
54 5   33     33 || $Apache::Session::Store::DBI::TableName;
55              
56             # Case 1: all requested fields are also indexed
57 5         33 my $indexed = $class->_tabInTab( \@fields, $index );
58 5         9 my $sth;
59 5 100       13 if ($indexed) {
60 1         3 my $fields = join( ',', 'id', map { s/'//g; $_ } @fields );
  2         3  
  2         6  
61 1         11 $sth = $dbh->prepare(
62             "SELECT $fields from $table_name where $query->{query}");
63 1         140 $sth->execute( @{ $query->{values} } );
  1         80  
64 1         10 return $sth->fetchall_hashref('id');
65             }
66              
67             # Case 1: at least one field isn't indexed, decoding is needed
68             else {
69 4         35 $sth =
70             $dbh->prepare(
71             "SELECT id,a_session from $table_name where $query->{query}");
72 4         537 $sth->execute( @{ $query->{values} } );
  4         282  
73 4         58 while ( my @row = $sth->fetchrow_array ) {
74 4     4   46 no strict 'refs';
  4         23  
  4         5338  
75 7         467 my $self = eval "&${class}::populate();";
76 7         22 my $sub = $self->{unserialize};
77 7         10 eval {
78 7         24 my $tmp = &$sub( { serialized => $row[1] } );
79 7 100       19 if (@fields) {
80 2         15 $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@fields);
81             }
82             else {
83 5         12 $res{ $row[0] } = $tmp;
84             }
85             };
86 7 50       31 if ($@) {
87 0         0 print STDERR "Error in session $row[0]: $@\n";
88 0         0 delete $res{ $row[0] };
89             }
90             }
91             }
92 4         120 return \%res;
93             }
94              
95             sub deleteIfLowerThan {
96 0     0 0 0 my ( $class, $args, $rule ) = @_;
97 0         0 my ( $query, %fields );
98             my $index =
99             ref( $args->{Index} )
100             ? $args->{Index}
101 0 0       0 : [ split /\s+/, $args->{Index} ];
102 0 0       0 if ( $rule->{or} ) {
    0          
103             $query = join ' OR ', map {
104 0         0 $fields{$_}++;
105 0         0 $class->_buildLowerThanExpression( $_, $rule->{or}->{$_} )
106             }
107 0         0 keys %{ $rule->{or} };
  0         0  
108             }
109             elsif ( $rule->{and} ) {
110             $query = join ' AND ', map {
111 0         0 $fields{$_}++;
112 0         0 $class->_buildLowerThanExpression( $_, $rule->{and}->{$_} )
113             }
114 0         0 keys %{ $rule->{and} };
  0         0  
115             }
116 0 0       0 if ( $rule->{not} ) {
117             $query = "($query) AND " . join(
118             ' AND ',
119             map {
120 0         0 $rule->{not}->{$_} =~ s/'/''/g;
121 0         0 $fields{$_}++;
122 0         0 "$_ <> '$rule->{not}->{$_}'"
123             }
124 0         0 keys %{ $rule->{not} }
  0         0  
125             );
126             }
127 0 0 0     0 return 0
128             unless ( $query and $class->_tabInTab( [ keys %fields ], $index ) );
129 0         0 my $dbh = $class->_classDbh($args);
130             my $table_name = $args->{TableName}
131 0   0     0 || $Apache::Session::Store::DBI::TableName;
132 0         0 my $rows = $dbh->do("DELETE FROM $table_name WHERE $query");
133 0 0       0 return 0 unless defined $rows;
134              
135 0 0       0 if (wantarray) {
136 0 0       0 $rows = 0 if $rows == -1;
137 0         0 return ( 1, $rows );
138             }
139             else {
140 0         0 return 1;
141             }
142             }
143              
144             # Let specialized modules override this syntax if they need to
145             sub _buildLowerThanExpression {
146 0     0   0 my ( $class, $field, $value ) = @_;
147 0         0 return "cast($field as integer) < $value";
148             }
149              
150             sub get_key_from_all_sessions {
151 6     6 0 1450 my $class = shift;
152 6         11 my $args = shift;
153 6         11 my $data = shift;
154              
155             my $table_name = $args->{TableName}
156 6   33     43 || $Apache::Session::Store::DBI::TableName;
157 6         23 my $dbh = $class->_classDbh($args);
158              
159             # Special case if all wanted fields are indexed
160 6 100 100     35 if ( $data and ref($data) ne 'CODE' ) {
161 2 50       7 $data = [$data] unless ( ref($data) );
162             my $index =
163             ref( $args->{Index} )
164             ? $args->{Index}
165 2 50       12 : [ split /\s+/, $args->{Index} ];
166              
167             # Test if one field isn't indexed
168 2         12 my $indexed = $class->_tabInTab( $data, $index );
169              
170             # OK, all fields are indexed
171 2 100       7 if ($indexed) {
172             my $sth =
173             $dbh->prepare_cached( 'SELECT id,'
174 1         2 . join( ',', map { s/'/''/g; $_ } @$data )
  2         4  
  2         13  
175             . " from $table_name" );
176 1         187 $sth->execute;
177 1         40 return $sth->fetchall_hashref('id');
178             }
179             }
180 5         36 my $sth = $dbh->prepare_cached("SELECT id,a_session from $table_name");
181 5         1811 $sth->execute;
182 5         15 my %res;
183             my $next = (
184             $args->{DataSource} =~ /^sybase/i
185             ? sub {
186 0     0   0 require Storable;
187 0         0 return Storable::thaw( pack( 'H*', $_[0] ) );
188             }
189             : $args->{DataSource} =~ /^mysql/i ? sub {
190 0     0   0 require MIME::Base64;
191 0         0 require Storable;
192 0         0 return Storable::thaw( MIME::Base64::decode_base64( $_[0] ) );
193             }
194             : undef
195 5 50       41 );
    50          
196 5         71 while ( my @row = $sth->fetchrow_array ) {
197 4     4   48 no strict 'refs';
  4         9  
  4         2347  
198 140         6269 my $self = eval "&${class}::populate();";
199 140         304 eval {
200 140         182 my $sub = $self->{unserialize};
201 140         310 my $tmp = &$sub( { serialized => $row[1] }, $next );
202 140 100       290 if ( ref($data) eq 'CODE' ) {
    100          
203 84         2085 $tmp = &$data( $tmp, $row[0] );
204 84 50       170 $res{ $row[0] } = $tmp if ( defined($tmp) );
205             }
206             elsif ($data) {
207 28 50       47 $data = [$data] unless ( ref($data) );
208 28         148 $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data);
209             }
210             else {
211 28         68 $res{ $row[0] } = $tmp;
212             }
213             };
214 140 50       447 if ($@) {
215 0         0 print STDERR "Error in session $row[0]: $@\n";
216 0         0 delete $res{ $row[0] };
217             }
218             }
219 5         89 return \%res;
220             }
221              
222             sub _classDbh {
223 11     11   22 my $class = shift;
224 11         20 my $args = shift;
225              
226 11 50       49 my $datasource = $args->{DataSource} or die "No datasource given !";
227 11         25 my $username = $args->{UserName};
228 11         22 my $password = $args->{Password};
229 11   50     111 my $dbh =
230             DBI->connect_cached( $datasource, $username, $password,
231             { RaiseError => 1, AutoCommit => 1 } )
232             || die $DBI::errstr;
233 11 50       3860 if ( $datasource =~ /^dbi:sqlite/i ) {
    0          
    0          
234 11         89 $dbh->{sqlite_unicode} = 1;
235             }
236             elsif ( $datasource =~ /^dbi:mysql/i ) {
237 0         0 $dbh->{mysql_enable_utf8} = 1;
238             }
239             elsif ( $datasource =~ /^dbi:pg/i ) {
240 0         0 $dbh->{pg_enable_utf8} = 1;
241             }
242 11         32 return $dbh;
243             }
244              
245             1;
246