remove prepare_dbh, use prepare_cached
[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;
6f28db48 31 return $self;
32}
33
39d453e4 34sub _dbh {
35 shift->{dbh};
6f28db48 36}
37
38sub fetch {
39 my ($self, $session_id) = @_;
39d453e4 40 my $table_name = $self->{table_name};
41 my $dbh = $self->_dbh;
42 my $sth = $dbh->prepare_cached("SELECT session_data FROM $table_name WHERE id = ?");
6f28db48 43 $sth->execute( $session_id );
44 my ($data) = $sth->fetchrow_array();
45 $sth->finish;
46 return $data ? $self->deserializer->( $data ) : ();
47}
48
49sub store {
50 my ($self, $session_id, $session) = @_;
39d453e4 51 my $table_name = $self->{table_name};
6f28db48 52
53 # XXX To be honest, I feel like there should be a transaction
54 # call here.... but Catalyst didn't have it, so I'm not so sure
55
39d453e4 56 my $sth = $self->_dbh->prepare_cached("SELECT 1 FROM $table_name WHERE id = ?");
6f28db48 57 $sth->execute($session_id);
58
59 # need to fetch. on some DBD's execute()'s return status and
60 # rows() is not reliable
61 my ($exists) = $sth->fetchrow_array();
62
63 $sth->finish;
64
39d453e4 65 if ($exists) {
66 my $sth = $self->_dbh->prepare_cached("UPDATE $table_name SET session_data = ? WHERE id = ?");
67 $sth->execute( $self->serializer->($session), $session_id );
68 }
69 else {
70 my $sth = $self->_dbh->prepare_cached("INSERT INTO $table_name (id, session_data) VALUES (?, ?)");
71 $sth->execute( $session_id , $self->serializer->($session) );
72 }
73
6f28db48 74}
75
76sub remove {
77 my ($self, $session_id) = @_;
39d453e4 78 my $table_name = $self->{table_name};
79 my $sth = $self->_dbh->prepare_cached("DELETE FROM $table_name WHERE id = ?");
6f28db48 80 $sth->execute( $session_id );
81 $sth->finish;
82}
83
841;
85
86__END__
87
7c2aa126 88=head1 NAME
89
90Plack::Session::Store::DBI - DBI-based session store
91
92=head1 SYNOPSIS
93
94 use Plack::Builder;
95 use Plack::Middleware::Session;
96 use Plack::Session::Store::DBI;
97
98 my $app = sub {
99 return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello Foo' ] ];
100 };
101
102 builder {
103 enable 'Session',
104 store => Plack::Session::Store::DBI->new(
105 dbh => DBI->connect( @connect_args )
106 );
107 $app;
108 };
109
110 # with custom serializer/deserializer
111
112 builder {
113 enable 'Session',
0e9a58b8 114 store => Plack::Session::Store::DBI->new(
7c2aa126 115 dbh => DBI->connect( @connect_args )
116 # YAML takes it's args the opposite order
117 serializer => sub { YAML::DumpFile( reverse @_ ) },
118 deserializer => sub { YAML::LoadFile( @_ ) },
119 );
120 $app;
121 };
122
123=head1 DESCRIPTION
124
125This implements a DBI based storage for session data. By
126default it will use L<Storable> and L<MIME::Base64> to serialize and
127deserialize the data, but this can be configured easily.
128
129This is a subclass of L<Plack::Session::Store> and implements
c4b2fb0e 130its full interface.
7c2aa126 131
132=head1 SESSION TABLE SCHEMA
133
6f28db48 134Your session table must have at least the following schema structure:
135
136 CREATE TABLE sessions (
137 id CHAR(72) PRIMARY KEY,
138 session_data TEXT
139 );
140
141Note that MySQL TEXT fields only store 64KB, so if your session data
142will exceed that size you'll want to move to MEDIUMTEXT, MEDIUMBLOB,
143or larger.
6f28db48 144
145=head1 AUTHORS
146
147Many aspects of this module were partially based upon Catalyst::Plugin::Session::Store::DBI
148
7c2aa126 149Daisuke Maki
150
151=head1 COPYRIGHT AND LICENSE
152
153Copyright 2009, 2010 Daisuke Maki C<< <daisuke@endeworks.jp> >>
154
155This library is free software; you can redistribute it and/or modify
156it under the same terms as Perl itself.
157=cut
158