File Coverage

blib/lib/Hash/Storage/Driver/DBI.pm
Criterion Covered Total %
statement 18 18 100.0
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 24 24 100.0


line stmt bran cond sub pod time code
1             package Hash::Storage::Driver::DBI;
2              
3             our $VERSION = 0.01;
4              
5 1     1   16158 use v5.10;
  1         4  
  1         34  
6 1     1   3 use strict;
  1         2  
  1         38  
7 1     1   3 use warnings;
  1         5  
  1         31  
8              
9 1     1   3 use Carp qw/croak/;
  1         1  
  1         60  
10 1     1   411 use Query::Abstract;
  1         49016  
  1         43  
11              
12 1     1   10 use base "Hash::Storage::Driver::Base";
  1         3  
  1         528  
13              
14             sub new {
15             my ($class, %args) = @_;
16              
17             my $self = $class->SUPER::new(%args);
18             croak "DBH REQUIRED" unless $self->{dbh};
19             croak "TABLE REQUIRED" unless $self->{table};
20              
21             return $self;
22             }
23              
24             sub init {
25             my ($self) = @_;
26             $self->{query_abstract} = Query::Abstract->new( driver => [
27             'SQL' => [ table => $self->{table} ]
28             ] );
29             }
30              
31             sub get {
32             my ( $self, $id ) = @_;
33              
34             my $sth = $self->{dbh}->prepare_cached("SELECT * FROM $self->{table} WHERE $self->{key_column} = ?");
35             $sth->execute($id);
36              
37             my $row = $sth->fetchrow_hashref();
38             $sth->finish();
39              
40             my $serialized = $row->{ $self->{data_column} };
41             return $self->{serializer}->deserialize($serialized);
42             }
43              
44             sub set {
45             my ( $self, $id, $fields ) = @_;
46             return unless keys %$fields;
47              
48             my $data = $self->get($id);
49             my $is_create = $data ? 0 : 1;
50              
51             # Prepare serialized data
52             $data ||= {};
53             @{$data}{ keys %$fields } = values %$fields;
54              
55             my $serialized = $self->{serializer}->serialize($data);
56              
57             # Prepare index columns
58             my @columns;
59             foreach my $column (keys %$fields) {
60             push @columns, $column if grep { $column eq $_ } @{ $self->{index_columns} || [] };
61             }
62              
63             my @values = @{$fields}{@columns};
64              
65             # Add serialized column
66             push @columns, $self->{data_column};
67             push @values, $serialized;
68              
69             my $sql = '';
70             my $bind_values = [@values];
71              
72             if ($is_create) {
73             my $values_cnt = @columns + 1;
74             $sql = "INSERT INTO $self->{table}(" . join(', ', @columns, $self->{key_column} ) . ") VALUES(" . join(', ', ('?')x $values_cnt) . ")";
75             push @$bind_values, $id;
76             } else {
77             my $update_str = join(', ', map { "$_=?" } @columns );
78             $sql = "UPDATE $self->{table} SET $update_str WHERE $self->{key_column} = ?";
79             push @$bind_values, $id;
80             }
81              
82             my $sth = $self->{dbh}->prepare_cached($sql);
83              
84             $sth->execute(@$bind_values);
85             $sth->finish();
86             }
87              
88             sub del {
89             my ( $self, $id ) = @_;
90             my $sql = "DELETE FROM $self->{table} WHERE $self->{key_column}=?";
91              
92             my $sth = $self->{dbh}->prepare_cached($sql);
93             $sth->execute($id);
94             $sth->finish();
95             }
96              
97             sub list {
98             my ( $self, @query ) = @_;
99              
100             my ($sql, $bind_values) = $self->{query_abstract}->convert_query(@query);
101              
102             my $sth = $self->{dbh}->prepare_cached($sql);
103             $sth->execute(@$bind_values);
104              
105             my $rows = $sth->fetchall_arrayref({});
106             $sth->finish();
107              
108              
109             return [ map { $self->{serializer}->deserialize(
110             $_->{ $self->{data_column} }
111             ) } @$rows ];
112             }
113              
114             sub count {
115             my ( $self, $filter ) = @_;
116             my ($where_str, $bind_values) = $self->{query_abstract}->convert_filter($filter);
117              
118             my $sql = "SELECT COUNT(*) FROM $self->{table} $where_str";
119              
120             my $sth = $self->{dbh}->prepare_cached($sql);
121             $sth->execute(@$bind_values);
122              
123             my $row = $sth->fetchrow_arrayref();
124             return $row->[0];
125             }
126              
127              
128             1;
129              
130             =head1 NAME
131              
132             Hash::Storage::Driver::DBI - DBI driver for Hash::Storage
133              
134             MODULE IS IN A DEVELOPMENT STAGE. DO NOT USE IT YET.
135              
136             =head1 SYNOPSIS
137              
138             my $st = Hash::Storage->new( driver => [ DBI => {
139             dbh => $dbh,
140             serializer => 'JSON',
141             table => 'users',
142             key_column => 'user_id',
143             data_column => 'serialized',
144             index_columns => ['age', 'fname', 'lname', 'gender']
145             }]);
146              
147             # Store hash by id
148             $st->set( 'user1' => { fname => 'Viktor', gender => 'M', age => '28' } );
149              
150             # Get hash by id
151             my $user_data = $st->get('user1');
152              
153             # Delete hash by id
154             $st->del('user1');
155              
156             =head1 DESCRIPTION
157              
158             Hash::Storage::Driver::DBI is a DBI Driver for Hash::Storage (multipurpose storage for hash). You can consider Hash::Storage object as a collection of hashes.
159             You can use it for storing users, sessions and a lot more data.
160              
161             =head1 OPTIONS
162              
163             =head2 dbh
164              
165             Database handler
166              
167             =head2 serializer
168              
169             Data::Serializer driver name
170              
171             =head2 table
172              
173             Table name to save data
174              
175             =head2 key_column
176              
177             column for saving object id
178              
179             =head2 data_column
180              
181             all data will be serialized in one field.
182              
183             =head2 index_columns
184              
185             List of colums to increase searches
186              
187             =head1 AUTHOR
188              
189             "koorchik", C<< <"koorchik at cpan.org"> >>
190              
191             =head1 BUGS
192              
193             Please report any bugs or feature requests to L
194              
195             =head1 ACKNOWLEDGEMENTS
196              
197              
198             =head1 LICENSE AND COPYRIGHT
199              
200             Copyright 2012 "koorchik".
201              
202             This program is free software; you can redistribute it and/or modify it
203             under the terms of either: the GNU General Public License as published
204             by the Free Software Foundation; or the Artistic License.
205              
206             See http://dev.perl.org/licenses/ for more information.
207              
208             =cut