fixed docs
[catagits/Web-Session.git] / lib / Plack / Session / Store / DBI.pm
CommitLineData
6f28db48 1package Plack::Session::Store::DBI;
2use strict;
3use warnings;
4
5# XXX Is there a notion of auto-expiry?
6
7our $VERSION = '0.10';
8our $AUTHORITY = 'cpan:STEVAN';
9
6f28db48 10use MIME::Base64 ();
11use Storable ();
12
13use parent 'Plack::Session::Store';
14
15use Plack::Util::Accessor qw[ dbh table_name serializer deserializer ];
16
17sub new {
18 my ($class, %params) = @_;
19
7c2aa126 20 if (! $params{dbh} ) {
21 die "DBI instance was not available in the argument list";
6f28db48 22 }
23
24 $params{table_name} ||= 'sessions';
25 $params{serializer} ||=
26 sub { MIME::Base64::encode_base64( Storable::nfreeze( $_[0] ) ) };
27 $params{deserializer} ||=
28 sub { Storable::thaw( MIME::Base64::decode_base64( $_[0] ) ) };
29
30 my $self = bless { %params }, $class;
31 $self->_prepare_dbh();
32 return $self;
33}
34
35sub _prepare_dbh {
36 my $self = shift;
6f28db48 37
7c2aa126 38 my $dbh = $self->{dbh};
6f28db48 39 # These are pre-cooked, so we can efficiently execute them upon request
40 my $table_name = $self->{table_name};
41 my %sql = (
42 get_session =>
43 "SELECT session_data FROM $table_name WHERE id = ?",
44
45 delete_session =>
46 "DELETE FROM $table_name WHERE id = ?",
47
48 # XXX argument list order matters for insert and update!
49 # (they should match, so we can execute them the same way)
50 # If you change this, be sure to change store() as well.
51 insert_session =>
52 "INSERT INTO $table_name (session_data, id) VALUES (?, ?)",
53 update_session =>
54 "UPDATE $table_name SET session_data = ? WHERE id = ?",
55
56 check_session =>
57 "SELECT 1 FROM $table_name WHERE id = ?",
58 );
59
60 while (my ($name, $sql) = each %sql ) {
61 $self->{"_sth_$name"} = $dbh->prepare($sql);
62 }
63}
64
65sub fetch {
66 my ($self, $session_id) = @_;
67 my $sth = $self->{_sth_get_session};
68 $sth->execute( $session_id );
69 my ($data) = $sth->fetchrow_array();
70 $sth->finish;
71 return $data ? $self->deserializer->( $data ) : ();
72}
73
74sub store {
75 my ($self, $session_id, $session) = @_;
76
77 # XXX To be honest, I feel like there should be a transaction
78 # call here.... but Catalyst didn't have it, so I'm not so sure
79
80 my $sth;
81
82 $sth = $self->{_sth_check_session};
83 $sth->execute($session_id);
84
85 # need to fetch. on some DBD's execute()'s return status and
86 # rows() is not reliable
87 my ($exists) = $sth->fetchrow_array();
88
89 $sth->finish;
90
91 $sth = ($exists) ?
92 $self->{_sth_update_session} : $self->{_sth_insert_session};
93
94 $sth->execute( $self->serializer->($session), $session_id );
95}
96
97sub remove {
98 my ($self, $session_id) = @_;
99 my $sth = $self->{_sth_delete_session};
100 $sth->execute( $session_id );
101 $sth->finish;
102}
103
1041;
105
106__END__
107
7c2aa126 108=head1 NAME
109
110Plack::Session::Store::DBI - DBI-based session store
111
112=head1 SYNOPSIS
113
114 use Plack::Builder;
115 use Plack::Middleware::Session;
116 use Plack::Session::Store::DBI;
117
118 my $app = sub {
119 return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello Foo' ] ];
120 };
121
122 builder {
123 enable 'Session',
124 store => Plack::Session::Store::DBI->new(
125 dbh => DBI->connect( @connect_args )
126 );
127 $app;
128 };
129
130 # with custom serializer/deserializer
131
132 builder {
133 enable 'Session',
0e9a58b8 134 store => Plack::Session::Store::DBI->new(
7c2aa126 135 dbh => DBI->connect( @connect_args )
136 # YAML takes it's args the opposite order
137 serializer => sub { YAML::DumpFile( reverse @_ ) },
138 deserializer => sub { YAML::LoadFile( @_ ) },
139 );
140 $app;
141 };
142
143=head1 DESCRIPTION
144
145This implements a DBI based storage for session data. By
146default it will use L<Storable> and L<MIME::Base64> to serialize and
147deserialize the data, but this can be configured easily.
148
149This is a subclass of L<Plack::Session::Store> and implements
150it's full interface.
151
152=head1 SESSION TABLE SCHEMA
153
6f28db48 154Your session table must have at least the following schema structure:
155
156 CREATE TABLE sessions (
157 id CHAR(72) PRIMARY KEY,
158 session_data TEXT
159 );
160
161Note that MySQL TEXT fields only store 64KB, so if your session data
162will exceed that size you'll want to move to MEDIUMTEXT, MEDIUMBLOB,
163or larger.
6f28db48 164
165=head1 AUTHORS
166
167Many aspects of this module were partially based upon Catalyst::Plugin::Session::Store::DBI
168
7c2aa126 169Daisuke Maki
170
171=head1 COPYRIGHT AND LICENSE
172
173Copyright 2009, 2010 Daisuke Maki C<< <daisuke@endeworks.jp> >>
174
175This library is free software; you can redistribute it and/or modify
176it under the same terms as Perl itself.
177=cut
178