File Coverage

blib/lib/HTTP/Session/Store/DBI.pm
Criterion Covered Total %
statement 64 66 96.9
branch 4 6 66.6
condition n/a
subroutine 11 11 100.0
pod 4 4 100.0
total 83 87 95.4


line stmt bran cond sub pod time code
1             package HTTP::Session::Store::DBI;
2              
3 2     2   85238 use Moose;
  2         924090  
  2         12  
4 2     2   12693 use Moose::Util::TypeConstraints;
  2         4  
  2         21  
5 2     2   6240 use DBI;
  2         17157  
  2         132  
6 2     2   1990 use MIME::Base64;
  2         2973  
  2         149  
7 2     2   16386 use Storable qw/nfreeze thaw/;
  2         6474  
  2         1508  
8              
9             our $VERSION = '0.02';
10             our $AUTHORITY = 'cpan:FAYLAND';
11              
12             subtype 'DBH'
13             => as 'Object';
14              
15             coerce 'DBH'
16             => from 'ArrayRef'
17             => via { DBI->connect(@$_) or die $DBI::errstr; };
18              
19             has 'dbh' => ( is => 'ro', isa => 'DBH', coerce => 1, required => 1 );
20              
21             has expires => (
22             is => 'ro',
23             isa => 'Int',
24             required => 1,
25             default => 3600,
26             );
27              
28             has 'sid_table' => (
29             is => 'ro',
30             isa => 'Str',
31             required => 1,
32             default => 'session',
33             );
34             has 'sid_col' => (
35             is => 'ro',
36             isa => 'Str',
37             required => 1,
38             default => 'sid',
39             );
40             has 'data_col' => (
41             is => 'ro',
42             isa => 'Str',
43             required => 1,
44             default => 'data',
45             );
46             has 'expires_col' => (
47             is => 'ro',
48             isa => 'Str',
49             required => 1,
50             default => 'expires',
51             );
52             has 'clean_thres' => (
53             is => 'ro',
54             isa => 'Num',
55             required => 1,
56             default => '0.001'
57             );
58              
59             sub select {
60 5     5 1 811 my ( $self, $session_id ) = @_;
61            
62 5         439 my $dbh = $self->dbh;
63 5         301 my $sid_table = $self->sid_table;
64 5         293 my $sid_col = $self->sid_col;
65 5         282 my $data_col = $self->data_col;
66 5         294 my $expires_col = $self->expires_col;
67 5         42 my $sql = qq~SELECT $data_col, $expires_col FROM $sid_table WHERE $sid_col = ?~;
68 5         73 my $sth = $dbh->prepare( $sql );
69 5         1959 $sth->execute( $session_id );
70 5         83 my ($data, $expires) = $sth->fetchrow_array;
71            
72 5 100       105 return unless ($data);
73 2 50       14 return unless ( $expires > time() );
74            
75 2         37 return thaw( decode_base64($data) );
76             }
77              
78             sub insert {
79 2     2 1 9144 my ($self, $session_id, $data) = @_;
80            
81 2         19 $data = encode_base64( nfreeze($data) );
82            
83 2         477 my $dbh = $self->dbh;
84 2         137 my $sid_table = $self->sid_table;
85 2         118 my $sid_col = $self->sid_col;
86 2         117 my $data_col = $self->data_col;
87 2         119 my $expires_col = $self->expires_col;
88 2         15 my $sql =qq~INSERT INTO $sid_table ($sid_col, $data_col, $expires_col) VALUES (?, ?, ?)~;
89 2         32 my $sth = $dbh->prepare($sql);
90 2         400 $sth->execute( $session_id, $data, time() + $self->expires );
91             }
92              
93             sub update {
94 1     1 1 644 my ($self, $session_id, $data) = @_;
95            
96 1         8 $data = encode_base64( nfreeze($data) );
97            
98 1         114 my $dbh = $self->dbh;
99 1         37 my $sid_table = $self->sid_table;
100 1         44 my $sid_col = $self->sid_col;
101 1         42 my $data_col = $self->data_col;
102 1         39 my $expires_col = $self->expires_col;
103 1         5 my $sql =qq~UPDATE $sid_table SET $data_col = ?, $expires_col = ? WHERE $sid_col = ?~;
104 1         10 my $sth = $dbh->prepare($sql);
105 1         106 $sth->execute( $data, time() + $self->expires, $session_id );
106             }
107              
108             sub delete {
109 1     1 1 1227 my ($self, $session_id) = @_;
110            
111 1         74 my $dbh = $self->dbh;
112 1         64 my $sid_table = $self->sid_table;
113 1         62 my $sid_col = $self->sid_col;
114 1         62 my $data_col = $self->data_col;
115 1         66 my $expires_col = $self->expires_col;
116 1         8 my $sql =qq~DELETE FROM $sid_table WHERE $sid_col = ?~;
117 1         12 my $sth = $dbh->prepare($sql);
118 1         118603 $sth->execute( $session_id );
119            
120 1 50       185 if ( rand() < $self->clean_thres ) {
121 0           my $time_now = time();
122 0           $dbh->do(qq~DELETE FROM $sid_table WHERE expires < $time_now~);
123             }
124             }
125              
126              
127 2     2   15 no Moose;
  2         4  
  2         18  
128 2     2   421 no Moose::Util::TypeConstraints;
  2         4  
  2         19  
129              
130             __PACKAGE__->meta->make_immutable;
131              
132             1;
133             __END__
134              
135             =head1 NAME
136              
137             HTTP::Session::Store::DBI - store session data in DBI for L<HTTP::Session>
138              
139             =head1 SYNOPSIS
140              
141             use HTTP::Session;
142            
143             my $session = HTTP::Session->new(
144             store => HTTP::Session::Store::DBI->new( {
145             dbh => ["dbi:SQLite:dbname=xxx", '', '', {RaiseError => 1}]
146             } ),
147             state => ...,
148             request => ...,
149             );
150              
151             =head1 DESCRIPTION
152              
153             store session data in DBI. read L<HTTP::Session> for usage.
154              
155             =head1 CONFIGURATION
156              
157             =over 4
158              
159             =item dbh
160              
161             ArrayRef which passes to DBI->connect(@$_)
162              
163             or Instance of DBI->connect
164              
165             =item expires
166              
167             session expire time(in seconds)
168              
169             =item sid_table
170              
171             the table name where session stores. default is 'session'
172              
173             =item sid_col
174              
175             the session_id column name. default is 'sid'
176              
177             =item data_col
178              
179             the data column name. default is 'data'
180              
181             =item expires_col
182              
183             the expires column name. default is 'expires'
184              
185             =item clean_thres
186              
187             default is '0.001'. because L<DBI> do NOT delete expired data itself, we have code in sub delete
188              
189             if ( rand() < $self->clean_thres ) {
190             my $time_now = time();
191             $dbh->do(qq~DELETE FROM $sid_table WHERE expires < $time_now~);
192             }
193              
194             set it to 0 if we do NOT want it.
195              
196             =back
197              
198             =head1 TABLE SQL
199              
200             SQLite:
201              
202             CREATE TABLE session (
203             sid VARCHAR(32) PRIMARY KEY,
204             data TEXT,
205             expires INTEGER UNSIGNED NOT NULL,
206             UNIQUE(sid)
207             );
208              
209             =head1 METHODS
210              
211             =over 4
212              
213             =item select
214              
215             =item update
216              
217             =item delete
218              
219             =item insert
220              
221             for internal use only
222              
223             =back
224              
225             =head1 SEE ALSO
226              
227             L<HTTP::Session>, L<DBI>
228              
229             =head1 AUTHOR
230              
231             Fayland Lam, C<< <fayland at gmail.com> >>
232              
233             =head1 COPYRIGHT & LICENSE
234              
235             Copyright 2008 Fayland Lam, all rights reserved.
236              
237             This program is free software; you can redistribute it and/or modify it
238             under the same terms as Perl itself.
239              
240             =cut