1 package Plack::Session::Store::DBI;
5 # XXX Is there a notion of auto-expiry?
8 our $AUTHORITY = 'cpan:STEVAN';
13 use parent 'Plack::Session::Store';
15 use Plack::Util::Accessor qw[ dbh table_name serializer deserializer ];
18 my ($class, %params) = @_;
20 if (! $params{dbh} ) {
21 die "DBI instance was not available in the argument list";
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] ) ) };
30 my $self = bless { %params }, $class;
31 $self->_prepare_dbh();
38 my $dbh = $self->{dbh};
39 # These are pre-cooked, so we can efficiently execute them upon request
40 my $table_name = $self->{table_name};
43 "SELECT session_data FROM $table_name WHERE id = ?",
46 "DELETE FROM $table_name WHERE id = ?",
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.
52 "INSERT INTO $table_name (session_data, id) VALUES (?, ?)",
54 "UPDATE $table_name SET session_data = ? WHERE id = ?",
57 "SELECT 1 FROM $table_name WHERE id = ?",
60 while (my ($name, $sql) = each %sql ) {
61 $self->{"_sth_$name"} = $dbh->prepare($sql);
66 my ($self, $session_id) = @_;
67 my $sth = $self->{_sth_get_session};
68 $sth->execute( $session_id );
69 my ($data) = $sth->fetchrow_array();
71 return $data ? $self->deserializer->( $data ) : ();
75 my ($self, $session_id, $session) = @_;
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
82 $sth = $self->{_sth_check_session};
83 $sth->execute($session_id);
85 # need to fetch. on some DBD's execute()'s return status and
86 # rows() is not reliable
87 my ($exists) = $sth->fetchrow_array();
92 $self->{_sth_update_session} : $self->{_sth_insert_session};
94 $sth->execute( $self->serializer->($session), $session_id );
98 my ($self, $session_id) = @_;
99 my $sth = $self->{_sth_delete_session};
100 $sth->execute( $session_id );
110 Plack::Session::Store::DBI - DBI-based session store
115 use Plack::Middleware::Session;
116 use Plack::Session::Store::DBI;
119 return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello Foo' ] ];
124 store => Plack::Session::Store::DBI->new(
125 dbh => DBI->connect( @connect_args )
130 # with custom serializer/deserializer
134 store => Plack::Session::Store::File->new(
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( @_ ) },
145 This implements a DBI based storage for session data. By
146 default it will use L<Storable> and L<MIME::Base64> to serialize and
147 deserialize the data, but this can be configured easily.
149 This is a subclass of L<Plack::Session::Store> and implements
152 =head1 SESSION TABLE SCHEMA
154 Your session table must have at least the following schema structure:
156 CREATE TABLE sessions (
157 id CHAR(72) PRIMARY KEY,
161 Note that MySQL TEXT fields only store 64KB, so if your session data
162 will exceed that size you'll want to move to MEDIUMTEXT, MEDIUMBLOB,
167 Many aspects of this module were partially based upon Catalyst::Plugin::Session::Store::DBI
171 =head1 COPYRIGHT AND LICENSE
173 Copyright 2009, 2010 Daisuke Maki C<< <daisuke@endeworks.jp> >>
175 This library is free software; you can redistribute it and/or modify
176 it under the same terms as Perl itself.