File Coverage

blib/lib/Data/Package/SQLite.pm
Criterion Covered Total %
statement 48 54 88.8
branch 11 20 55.0
condition 5 7 71.4
subroutine 14 14 100.0
pod 3 3 100.0
total 81 98 82.6


line stmt bran cond sub pod time code
1             package Data::Package::SQLite;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Data::Package::SQLite - A data package for a SQLite database
8              
9             =head1 SYNOPSIS
10              
11             ### Creating a SQLite data package
12            
13             package My::Data;
14            
15             use strict;
16             use base 'Data::Package::SQLite';
17            
18             sub sqlite_locate { file => '/var/cache/mydata.sqlite' }
19            
20             1;
21            
22             ### Using your SQLite data package
23            
24             use My::Data;
25            
26             # Default data access
27             $dbh = My::Data->get;
28            
29             # ... or if you want to be explicit
30             $dbh = My::Data->get('DBI::db');
31              
32             =head1 DESCRIPTION
33              
34             One of the best ways to distribute medium-sized (100k - 100meg) packages
35             containing datasets is using L databases.
36              
37             It allows you to have full SQL access to your data, and you can still
38             provide the data as a single file that does not need user/password access
39             and provides it's own security model (tied to filesystem access).
40              
41             C is a L sub-class for providing
42             simplified read-only access to these databases in the form of a L
43             connection handle, without the caller needing to know anything about
44             where the data is actually stored.
45              
46             =head1 METHODS
47              
48             Although the primary interface when using a C
49             module should be the same as for any other L module,
50             some additional methods are defined for people creating their own
51             sub-classes of C.
52              
53             =cut
54              
55 2     2   92848 use 5.005;
  2         7  
  2         71  
56 2     2   10 use strict;
  2         5  
  2         59  
57 2     2   29 use base 'Data::Package';
  2         3  
  2         1709  
58 2     2   26409 use Carp ();
  2         3  
  2         29  
59 2     2   1825 use File::ShareDir ();
  2         5014  
  2         44  
60 2     2   13 use Params::Util qw{_STRING _CLASS};
  2         3  
  2         122  
61 2     2   11 use DBI;
  2         4  
  2         75  
62              
63 2     2   10 use vars qw{$VERSION};
  2         3  
  2         73  
64             BEGIN {
65 2     2   933 $VERSION = '1.01';
66             }
67              
68             # Check the SQLite driver is available
69             unless ( grep { $_ eq 'SQLite' } DBI->available_drivers ) {
70             Carp::croak("SQLite DBI driver is not installed");
71             }
72              
73             # This class only provides a database handle
74 5     5   12271 sub _provides { 'DBI::db' }
75              
76             # Load the database handle
77             sub __as_DBI_db {
78 4     4   302 my $self = shift;
79              
80             # Create the database handle
81 4         12 my $dbh = DBI->connect( $self->sqlite_dsn, "", "" );
82 4 50       1533 unless ( $dbh ) {
83 0         0 Carp::croak("SQLite connection failed: $DBI::errstr");
84             }
85              
86 4         11 return $dbh;
87             }
88              
89             =pod
90              
91             =head2 sqlite_dsn
92              
93             The C method return a valid L dsn for the creation
94             of the database handle. For any C package that
95             you C a database handle from, the C method will
96             always return the location of the database that was loaded.
97              
98             When creating a sub-class, you should not return this directly, but
99             are encouraged to instead define your own C or even better
100             your own C.
101              
102             Returns a DSN string, or throws an exception on error.
103              
104             =cut
105              
106             sub sqlite_dsn {
107 7     7 1 726 my $self = shift;
108 7         16 my $dbfile = $self->sqlite_file;
109 7 50       8506 unless ( _STRING($dbfile) ) {
110 0         0 Carp::croak("SQLite file name not provided, or not a string");
111             }
112 7 50       108 unless ( -f $dbfile ) {
113 0         0 Carp::croak("SQLite file '$dbfile' does not exist");
114             }
115 7 50       110 unless ( -r $dbfile ) {
116 0         0 Carp::croak("SQLite file '$dbfile' cannot be read");
117             }
118 7         46 return "dbi:SQLite:dbname=$dbfile";
119             }
120              
121             =pod
122              
123             =head2 sqlite_file
124              
125             sub sqlite_file { '/var/cache/my_class/data.sqlite' }
126              
127             The C method returns the location of the SQLite file to
128             be loaded.
129              
130             Please note that the fact a file name is returned by this method does
131             not necesarily mean it exists, because in some cases incorrect file
132             names can be generated, or a sub-class might defined this method
133             (incorrectly) directly.
134              
135             Returns a file path string, or throws an exception in some error
136             situations.
137              
138             =cut
139              
140             sub sqlite_file {
141 10     10 1 3136 my $self = shift;
142 10         35 my @location = $self->sqlite_location;
143 10 50       65 my $type = _STRING(shift @location)
144             or Carp::croak('No or bad SQLite location type provided');
145              
146 10 50       44 if ( $type eq 'file' ) {
    100          
    50          
147 0         0 return shift @location;
148              
149             } elsif ( $type eq 'dist_file' ) {
150 3 50       11 my $dist = _STRING(shift @location)
151             or Carp::croak('No dist_file distribution provided');
152 3   50     13 my $file = _STRING(shift @location) || 'data.sqlite';
153 3         16 return File::ShareDir::dist_file( $dist, $file );
154              
155             } elsif ( $type eq 'module_file' ) {
156 7 50       191 my $module = _CLASS(shift @location)
157             or Carp::croak('Invalid or no module name provided');
158 7   100     86 my $file = _STRING(shift @location) || 'data.sqlite';
159 7         25 return File::ShareDir::module_file( $module, $file );
160              
161             } else {
162 0         0 Carp::croak("Unknown or unsupported location type '$type'");
163             }
164             }
165              
166             =pod
167              
168             =head2 sqlite_location
169              
170             # A general file location somewhere
171             sub sqlite_location { file => '/var/cache/my_class/data.sqlite' }
172            
173             # The default data.sqlite for a distribution
174             sub sqlite_location { dist_file => 'My-Dist' }
175            
176             # A specific file for a distribution
177             sub sqlite_location { dist_file => 'My-Dist', 'sqlite.db' }
178            
179             # The default data.sqlite for a module
180             sub sqlite_location { module_file => 'My::Module' }
181            
182             # A specific file for a module
183             sub sqlite_location { module_file => 'My::Module', 'sqlite.db' }
184              
185             The C method is the primary method for sub-classes to
186             specify the location of the SQLite database file.
187              
188             It should return a simple 2-3 element list, consisting of a location
189             type and 1 or more location values.
190              
191             The C method currently accepts 3 location types.
192              
193             =over 4
194              
195             =item file
196              
197             Mostly provides a direct pass-through to C.
198              
199             Takes a second param of the location of the file as a simple string.
200              
201             =item dist_file
202              
203             The C option provides access to the functionality provided
204             by the L function C.
205              
206             It takes two additional values, the name of the distribution and the
207             name of the file within the dist dir.
208              
209             If the file name is not provided, a default value of F
210             is used.
211              
212             =item module_file
213              
214             The C option provides access to the functionality provided
215             by the L function C.
216              
217             It takes two additional values, the name of the module and the
218             name of the file within the dist dir.
219              
220             If the file name is not provided, a default value of F
221             is used.
222              
223             =back
224              
225             If not provided, the default implementation of C will
226             return C<( module_file =E $class )>, where C<$class> is the name
227             of the L sub-class.
228              
229             =cut
230              
231             sub sqlite_location {
232 5   66 5 1 816119 my $class = ref($_[0]) || "$_[0]";
233              
234             # We don't know for sure that the class actually has
235             # a data.sqlite file, but it is the best guess.
236 5         19 return ( 'module_file' => $class );
237             }
238              
239             1;
240              
241             =pod
242              
243             =head1 SUPPORT
244              
245             Bugs should be B be reported via the CPAN bug tracker at:
246              
247             L
248              
249             For other issues, contact the author.
250              
251             =head1 AUTHORS
252              
253             Adam Kennedy Eadamk@cpan.orgE
254              
255             =head1 SEE ALSO
256              
257             L, L, L
258              
259             =head1 COPYRIGHT
260              
261             Copyright 2006 Adam Kennedy.
262              
263             This program is free software; you can redistribute
264             it and/or modify it under the same terms as Perl itself.
265              
266             The full text of the license can be found in the
267             LICENSE file included with this module.
268              
269             =cut