1 package Plack::Session::Store::DBI;
5 # XXX Is there a notion of auto-expiry?
8 our $AUTHORITY = 'cpan:STEVAN';
14 use parent 'Plack::Session::Store';
16 use Plack::Util::Accessor qw[ dbh table_name serializer deserializer ];
19 my ($class, %params) = @_;
21 if (! $params{dbh} ) {
22 die "DBI instance was not available in the argument list";
25 $params{table_name} ||= 'sessions';
26 $params{serializer} ||=
27 sub { MIME::Base64::encode_base64( Storable::nfreeze( $_[0] ) ) };
28 $params{deserializer} ||=
29 sub { Storable::thaw( MIME::Base64::decode_base64( $_[0] ) ) };
31 my $self = bless { %params }, $class;
32 $self->_prepare_dbh();
39 my $dbh = $self->{dbh};
40 # These are pre-cooked, so we can efficiently execute them upon request
41 my $table_name = $self->{table_name};
44 "SELECT session_data FROM $table_name WHERE id = ?",
47 "DELETE FROM $table_name WHERE id = ?",
49 # XXX argument list order matters for insert and update!
50 # (they should match, so we can execute them the same way)
51 # If you change this, be sure to change store() as well.
53 "INSERT INTO $table_name (session_data, id) VALUES (?, ?)",
55 "UPDATE $table_name SET session_data = ? WHERE id = ?",
58 "SELECT 1 FROM $table_name WHERE id = ?",
61 while (my ($name, $sql) = each %sql ) {
62 $self->{"_sth_$name"} = $dbh->prepare($sql);
67 my ($self, $session_id) = @_;
68 my $sth = $self->{_sth_get_session};
69 $sth->execute( $session_id );
70 my ($data) = $sth->fetchrow_array();
72 return $data ? $self->deserializer->( $data ) : ();
76 my ($self, $session_id, $session) = @_;
78 # XXX To be honest, I feel like there should be a transaction
79 # call here.... but Catalyst didn't have it, so I'm not so sure
83 $sth = $self->{_sth_check_session};
84 $sth->execute($session_id);
86 # need to fetch. on some DBD's execute()'s return status and
87 # rows() is not reliable
88 my ($exists) = $sth->fetchrow_array();
93 $self->{_sth_update_session} : $self->{_sth_insert_session};
95 $sth->execute( $self->serializer->($session), $session_id );
99 my ($self, $session_id) = @_;
100 my $sth = $self->{_sth_delete_session};
101 $sth->execute( $session_id );
111 Plack::Session::Store::DBI - DBI-based session store
116 use Plack::Middleware::Session;
117 use Plack::Session::Store::DBI;
120 return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello Foo' ] ];
125 store => Plack::Session::Store::DBI->new(
126 dbh => DBI->connect( @connect_args )
131 # with custom serializer/deserializer
135 store => Plack::Session::Store::File->new(
136 dbh => DBI->connect( @connect_args )
137 # YAML takes it's args the opposite order
138 serializer => sub { YAML::DumpFile( reverse @_ ) },
139 deserializer => sub { YAML::LoadFile( @_ ) },
146 This implements a DBI based storage for session data. By
147 default it will use L<Storable> and L<MIME::Base64> to serialize and
148 deserialize the data, but this can be configured easily.
150 This is a subclass of L<Plack::Session::Store> and implements
153 =head1 SESSION TABLE SCHEMA
155 Your session table must have at least the following schema structure:
157 CREATE TABLE sessions (
158 id CHAR(72) PRIMARY KEY,
162 Note that MySQL TEXT fields only store 64KB, so if your session data
163 will exceed that size you'll want to move to MEDIUMTEXT, MEDIUMBLOB,
168 Many aspects of this module were partially based upon Catalyst::Plugin::Session::Store::DBI
172 =head1 COPYRIGHT AND LICENSE
174 Copyright 2009, 2010 Daisuke Maki C<< <daisuke@endeworks.jp> >>
176 This library is free software; you can redistribute it and/or modify
177 it under the same terms as Perl itself.