File Coverage

blib/lib/SQLite/Abstract.pm
Criterion Covered Total %
statement 163 182 89.5
branch 41 60 68.3
condition 6 12 50.0
subroutine 30 36 83.3
pod 19 22 86.3
total 259 312 83.0


line stmt bran cond sub pod time code
1             package SQLite::Abstract;
2              
3 7     7   168942 use strict;
  7         20  
  7         400  
4 7     7   34 use warnings;
  7         12  
  7         190  
5 7     7   35 use Carp;
  7         14  
  7         1176  
6 7     7   513205 use DBI;
  7         139874  
  7         4161  
7              
8             our $VERSION = '0.14';
9              
10             my $td = {
11             week =>
12             { 0, 'Sun', 1, 'Mon', 2, 'Tue', 3, 'Wed', 4, 'Thu', 5, 'Fri', 6, 'Sat' },
13             month => {
14             '01' => 'Jan',
15             '02' => 'Feb',
16             '03' => 'Mar',
17             '04' => 'Apr',
18             '05' => 'May',
19             '06' => 'Jun',
20             '07' => 'Jul',
21             '08' => 'Aug',
22             '09' => 'Sep',
23             '10' => 'Oct',
24             '11' => 'Nov',
25             '12' => 'Dec',
26             }
27             };
28              
29             sub new {
30 7     7 1 766 my $class = shift;
31 7         18 my $data = shift;
32 7         13 my $self;
33 7         196 my $attrs = {
34             AutoCommit => 0,
35             PrintError => 0,
36             RaiseError => 1,
37             };
38              
39 7 100       34 if ( not ref $data eq 'HASH' ) {
40 6         11 my $dbtype = shift;
41 6         13 my $tablename = shift;
42 6         20 $self->{'dbname'} = $data;
43 6 50       28 $self->{'dbtype'} = $dbtype ? $dbtype : "dbi:SQLite2:dbname";
44 6         18 $self->{'tablename'} = $tablename;
45 6         18 $self->{'attrs'} = $attrs;
46             }
47             else {
48 1 50       11 $self = {
49             dbname => $data->{'DB'},
50             dbtype => $data->{'DSN'},
51             tablename => $data->{'TABLE'},
52             attrs => ref $data->{'attrs'} eq 'HASH'
53             ? $data->{'attrs'}
54             : $attrs
55             };
56             }
57              
58 7 50       31 $class eq __PACKAGE__
59             or croak _err_msg("constructor not called as class method");
60              
61 7 50       567 -e $self->{'dbname'}
62             or croak _err_msg("no database defined");
63 7 50       929 -f $self->{'dbname'}
64             or croak _err_msg("no such database $self->{dbname}");
65              
66 7         100 $self->{'dbh'} = DBI->connect( qq/$self->{dbtype}=$self->{dbname}/,
67             q//, q//, $self->{'attrs'} );
68              
69 7     0   37632 $self->{'BEGIN'} = sub { $self->{'dbh'}->begin_work };
  0         0  
70 7     20   44 $self->{'COMMIT'} = sub { $self->{'dbh'}->commit };
  20         2030456  
71 7     1   47 $self->{'ROLLBACK'} = sub { $self->{'dbh'}->rollback };
  1         268  
72              
73 7         49 return bless $self, $class;
74              
75             }
76              
77             sub table : lvalue {
78 7 100   7 1 302 $_[1]
79             ? $_[0]->{q{tablename}} =
80             $_[1]
81             : $_[0]->{q{tablename}};
82             }
83              
84             sub tables {
85 0     0 1 0 my $self = shift;
86 7     7   84 no strict 'refs';
  7         16  
  7         17193  
87              
88 0         0 map { $_->[0] } $self->select(
  0         0  
89             q/
90             SELECT name FROM
91             (SELECT * FROM sqlite_master UNION ALL
92             SELECT * FROM sqlite_temp_master)
93             WHERE type='table'
94             ORDER BY name;
95             /
96             );
97             }
98              
99             sub localtime {
100 2     2 1 4 my $self = shift;
101 2         4 my $ps = shift;
102              
103 2 100       7 if ($ps) {
104 1         6 my @td = split q/ /, $self->select(
105             q/
106             select strftime("%w %m %d %H:%M:%S %Y",'now','localtime');
107             /
108             )->[0];
109 1         5 $td[0] = $td->{q/week/}{ $td[0] };
110 1         5 $td[1] = $td->{q/month/}{ $td[1] };
111              
112 1         33 return join q/ /, @td;
113             }
114              
115 1         5 return join q/ /, map { $_->[0] } $self->select(
  1         32  
116             q/
117             select datetime('now','localtime');
118             /
119             );
120             }
121              
122             sub time {
123 1     1 1 3 my $self = shift;
124              
125 1         5 return join q/ /, map { $_->[0] } $self->select(
  1         9  
126             q/
127             select strftime("%s",'now');
128             /
129             );
130              
131             }
132              
133             sub time_ahead {
134 1     1 1 2 my $self = shift;
135 1         4 my $ahead = "@_";
136              
137 1         6 return join q/ /, map { $_->[0] } $self->select(
  1         27  
138             qq/
139             select datetime('now','localtime',$ahead);
140             /
141             );
142              
143             }
144              
145             sub create_table {
146 2     2 1 12 my $self = shift;
147 2   33     11 my $tablename = shift || $self->{tablename};
148              
149 2         17 $self->do(
150             qq/
151             CREATE TABLE $tablename ( @_ );
152             /
153             );
154             }
155              
156             sub alter {
157 0     0 0 0 my $self = shift;
158 0         0 my $query = shift;
159              
160 0         0 $self->_check_table;
161 0         0 $self->do(
162             qq/
163             ALTER TABLE $self->{tablename} $query;
164             /
165             );
166             }
167              
168             sub drop_table {
169 1     1 1 4 my $self = shift;
170 1   33     6 my $tablename = shift || $self->{tablename};
171              
172 1         7 $self->do(
173             qq/
174             DROP TABLE $tablename;
175             VACUUM;
176             /
177             );
178             }
179              
180             sub insert {
181 2     2 1 2621 my $self = shift;
182 2         4 my $columns = $_[0];
183 2   66     11 my $data = $_[1] || $_[0];
184 2         5 my $sth = q{};
185 2         3 my $counter = 0;
186              
187 2         10 $self->_check_table;
188              
189             #~ $self->{q{BEGIN}}->();
190              
191 2 100       8 if ( @_ == 2 ) {
192 1         5 my $prep_columns = join( ',', @$columns );
193 1         14 my $prep_data = join( ',', split '', ( '?' x @$columns ) );
194 1         17 $sth = $self->{q{dbh}}->prepare(
195             qq/
196             INSERT INTO $self->{tablename} ($prep_columns)
197             VALUES ($prep_data);
198             /
199             );
200             }
201             else {
202 1         3 my $prep_data = join( ',', ( split '', ( '?' x @{ $data->[0] } ) ) );
  1         9  
203 1         15 $sth = $self->{q{dbh}}->prepare(
204             qq/
205             INSERT INTO $self->{tablename} VALUES ($prep_data);
206             /
207             );
208             }
209              
210 2         136 for (@$data) {
211 1404 50       48321 $sth->execute(@$_) and $counter++;
212             }
213              
214 2         20 $self->_END_;
215              
216 2         88 return $counter;
217             }
218              
219             sub replace {
220 0     0 0 0 my $self = shift;
221 0         0 my $query = shift;
222              
223 0         0 $self->_check_table;
224 0         0 $self->do(
225             qq/
226             REPLACE INTO $self->{tablename} $query;
227             /
228             );
229             }
230              
231             sub create_view {
232 1     1 1 3 my $self = shift;
233 1         2 my $view_name = shift;
234 1         2 my $select = shift;
235              
236 1         4 $self->_check_table;
237 1         6 $self->do(
238             qq/
239             CREATE VIEW $view_name AS $select;
240             /
241             );
242             }
243              
244             sub drop_view {
245 1     1 1 3 my $self = shift;
246 1         3 my $view_name = shift;
247              
248 1         3 $self->_check_table;
249 1         6 $self->do(
250             qq/
251             DROP VIEW $view_name;
252             /
253             );
254             }
255              
256             sub delete {
257 2     2 1 8 my $self = shift;
258 2         4 my $query = shift;
259              
260 2         9 $self->_check_table;
261 2         12 $self->do(
262             qq/
263             DELETE FROM $self->{tablename} $query;
264             /
265             );
266             }
267              
268             sub delete_all {
269 0     0 1 0 shift->delete(q/WHERE 1=1/);
270             }
271              
272             sub update {
273 2     2 1 10 my $self = shift;
274 2         5 my $query = shift;
275              
276 2         9 $self->_check_table;
277 2         13 $self->do(
278             qq/
279             UPDATE $self->{tablename} SET $query;
280             /
281             );
282             }
283              
284             sub select {
285 12     12 1 23 my $self = shift;
286 12         16 my $query = shift;
287 12         16 my $type = shift;
288 12         15 my $result;
289              
290 12         31 $self->_check_table;
291              
292 12   66     32 $query ||= qq/SELECT * FROM $self->{q{tablename}}/;
293 12         235 $query =~ s/^\s*(\w*\s*ALL\s*)/ * /i;
294              
295 12 100       42 if ( not $query =~ /^\s*SELECT\s+/i ) {
296 7 100       22 if ( $query =~ /^\s*\*/ ) {
297 4         36 $query =~ s/^\s*\*(.*)/SELECT * FROM
298             $self->{q{tablename}} $1/;
299             }
300             else {
301 3         30 $query =~ s/^\s*(\w+(\s*,\s*\w+)*)/SELECT $1 FROM
302             $self->{q{tablename}} /;
303             }
304             }
305              
306 12         201 local $self->{q{dbh}}->{q{RaiseError}} = 1;
307              
308 12 100       34 if (wantarray) {
309 5 50       7 if ( my @data = @{ $self->{q{dbh}}->selectall_arrayref($query) } ) {
  5         40  
310 5         1686 $self->_END_;
311 5 100       20 @data = map { $_->[0] } @data
  1         5  
312             if ref $type eq 'SCALAR';
313 5         65 return @data;
314             }
315             }
316             else {
317 7         20 local $_ = join( '_', $query );
318 7 50       21 if ( not $self->{$_} ) {
319 7         38 $self->{$_} = $self->{q{dbh}}->prepare($query);
320 7         2367 $self->{$_}->execute;
321 7         536 $result = [ $self->{$_}->fetchrow_array ];
322             }
323             else {
324 0         0 $result = [ $self->{$_}->fetchrow_array ];
325             }
326              
327 7         20 $self->{q/select/}->{q/last/} = $result;
328              
329 7 100       124 return @$result
    50          
330             ? ref $type eq 'SCALAR'
331             ? $result->[0]
332             : $result
333             : undef $self->{$_};
334             }
335             }
336              
337             sub last {
338 1     1 0 8 shift->{q/select/}->{q/last/};
339             }
340              
341             sub count {
342 2     2 1 5 my $self = shift;
343 2         5 my $query = shift;
344              
345 2         7 $self->_check_table;
346              
347 2 50       42 my $count = $query
348             ? $self->{q{dbh}}->selectall_arrayref(
349             qq/
350             SELECT count(*) FROM $self->{tablename} $query
351             /
352             )
353             : $self->{q{dbh}}->selectall_arrayref(
354             qq/
355             SELECT count(*) FROM $self->{tablename}
356             /
357             );
358              
359 2         975 $self->_END_;
360              
361 2         19 return $count->[0][0];
362             }
363              
364             sub sum {
365 1     1 1 13 shift->count(@_);
366             }
367              
368             sub _END_ {
369 9     9   18 my $self = shift;
370              
371 9         37 $self->{q{COMMIT}}->();
372             $self->{dbh}->errstr
373 9 50       141 and eval { $self->{q{ROLLBACK}}->() };
  0         0  
374             }
375              
376             sub do {
377 12     12 1 58 shift->_do_(@_);
378             }
379              
380             sub _do_ {
381 12     12   71 my $self = shift;
382 12         47 my $query = "@_";
383 12         21 my $affected;
384              
385 12         33 eval {
386 12         160 $affected = $self->{q{dbh}}->do($query);
387 11         7649 $self->{q{COMMIT}}->();
388             };
389              
390 12 100       1222 if ( $self->{q{dbh}}->errstr ) {
391 1         5 $self->err = $@;
392 1         9 eval { $self->{q{ROLLBACK}}->() };
  1         3  
393 1 50       26 if ( $self->{q{dbh}}->{q{RaiseError}} ) {
394 1         4 croak $self->err;
395             }
396             else {
397 0         0 carp $self->err;
398 0         0 return undef;
399             }
400             }
401             else {
402 11 100       477 return $affected == 0
403             ? "0E0"
404             : $affected;
405             }
406             }
407              
408             sub _check_table {
409 22     22   36 my $self = shift;
410 22 50       82 $self->{q{tablename}}
411             or croak _err_msg("missing table name");
412             }
413              
414             sub _err_msg {
415 0     0   0 __PACKAGE__ . q/:/ . (caller)[2] . q/:/ . __LINE__ . q/: / . "@_";
416             }
417              
418             sub err : lvalue {
419 3 50   3 1 291 $_[1]
420             ? $_[0]->{q{err}} = $_[1]
421             : $_[0]->{q{err}};
422             }
423              
424             sub AUTOLOAD {
425 3     3   18 my $self = shift;
426 3         5 my $query = shift;
427 3         5 my $tmp = shift;
428              
429 3 50       11 $tmp and $query = $tmp;
430 3 50       8 $query or $query = q{};
431              
432 3         5 our $AUTOLOAD;
433 3         24 ( my $method = $AUTOLOAD ) =~ s/.*:://s;
434              
435 3 50       15 if ( $method =~ /^select_(\w+)/i ) {
436 3         12 my $fields = join ',', split /_/, $1;
437 3 50       10 if ($fields) {
438 3         5 $query =~ s/^\s*SELECT.+?FROM\s+\S+//;
439 3 50       21 return $fields !~ /\,/
440             ? $self->select( "$fields $query", \$0 )
441             : $self->select("$fields $query");
442             }
443             }
444              
445 0         0 croak _err_msg("method $method does not exist");
446             }
447              
448             sub DESTROY {
449 1     1   3 my $self = shift;
450 1         2 $self->{q{dbh}} = undef;
451 1         106 $self = undef;
452             }
453              
454             1
455              
456             __END__