File Coverage

blib/lib/SQLite/DB.pm
Criterion Covered Total %
statement 135 148 91.2
branch 44 62 70.9
condition 9 14 64.2
subroutine 21 23 91.3
pod 13 15 86.6
total 222 262 84.7


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; mode:folding -*-
2              
3             package SQLite::DB;
4              
5             # {{{ BEGIN
6             #
7             BEGIN {
8 8     8   78358 require Exporter;
9             }
10             # }}}
11             # {{{ use block
12             #
13 8     8   43 use strict;
  8         14  
  8         339  
14 8     8   36 use Exporter;
  8         17  
  8         266  
15 8     8   30310 use DBI;
  8         204220  
  8         618  
16 8     8   12774 use DBD::SQLite;
  8         88654  
  8         466  
17              
18 8         1068 use constant { INVALID => 0, # SQL Statment types
19             SELECT => 1,
20             INSERT => 2,
21             UPDATE => 3,
22             DELETE => 4,
23             CREATE => 5,
24 8     8   82 DROP => 6,};
  8         16  
25              
26 8     8   51 use base 'Exporter';
  8         18  
  8         22748  
27              
28             # }}}
29             # {{{ variable declarations
30              
31             our @ISA = ('Exporter');
32             our @EXPORT = qw(connect disconnect transaction_mode commit exec
33             select get_dboptionlist get_dblist get_error);
34              
35             our $VERSION = '0.04';
36              
37             my $last_rowid = undef;
38             my $affected_rows = 0;
39             my @transaction_errors;
40              
41             # }}}
42              
43             # {{{ new Object Constructor
44             #
45             # Creates object based on given dbfile.
46             #
47             sub new {
48 7     7 1 93 my $class = shift;
49 7         50 my $self = { dbfile => shift,
50             dbconn => undef,
51             dberror => undef,};
52              
53 7         23 bless $self,$class;
54              
55 7         33 return $self;
56             }
57             # }}}
58             # {{{ connect Connect to the database
59             #
60             # Returns 1 if sucessfull, 0 otherwise.
61             #
62             sub connect {
63 7     7 1 2909 my $this = shift;
64 7         136 my $db = DBI->connect("dbi:SQLite:dbname=".$this->{dbfile},"","");
65              
66 7         15532 $db->{PrintError} = 0;
67 7         46 $db->{RaiseError} = 0;
68              
69 7 50       55 return 0 if ($this->check_error(__PACKAGE__."::connect - Error while connecting to DBI :"));
70              
71 7 50       32 if (!defined $db) {
72 0         0 $this->{dberror} = "Cannot connect to databases: $DBI::errstr\n";
73 0         0 return 0;
74             }
75              
76 7         21 $this->{dbconn} = $db;
77              
78 7         38 return 1;
79             }
80             # }}}
81             # {{{ disconnect Diconnect to the database
82             #
83             sub disconnect {
84 7     7 1 3858 my $this = shift;
85              
86 7 50       850 $this->{dbconn}->disconnect || return 0;
87 7         27 $this->{dbconn} = undef;
88              
89 7         660 return 1;
90             }
91             # }}}
92             # {{{ transaction_mode Start transaction mode
93             #
94             sub transaction_mode {
95 3     3 1 10 my $this = shift;
96              
97 3         49 @transaction_errors = ();
98 3         41 $this->{dbconn}->{AutoCommit} = 0;
99              
100             }
101             # }}}
102             # {{{ commit Commit transaction
103             #
104             sub commit {
105 3     3 1 6 my $this = shift;
106 3         7 my $result = 1;
107 3         5 my $error;
108 3 100       67 return 1 if ($this->{dbconn}->{AutoCommit});
109              
110 2 100       12 eval { $this->{dbconn}->commit } if !(@transaction_errors>0);
  1         178606  
111              
112 2 100 66     42 if ($@ || @transaction_errors>0) { # Check if errors occurred in the transaction
113 1         2 $result = 0;
114 1 50       8 $error = ($@) ? $@ : join "\n",@transaction_errors;
115 1         4 $this->{dberror} = "DBSqlite::DB::commit - Error in transaction because $error";
116 1         3 eval {$this->{dbconn}->rollback};
  1         185  
117             }
118              
119 2         46 $this->{dbconn}->{AutoCommit} = 1;
120              
121 2         25 return $result;
122             }
123              
124             # }}}
125             # {{{ rollback Rollback transaction
126             #
127             sub rollback {
128 2     2 1 5 my $this = shift;
129 2         5 my $result = 1;
130              
131 2 100       28 return 1 if ($this->{dbconn}->{AutoCommit});
132              
133 1         5272 $this->{dbconn}->rollback;
134              
135 1 50       25 if ($@) { # Check if errors occurred in the transaction
136 0         0 $result = 0;
137 0         0 $this->{dberror} = "DBSqlite::DB::rollback - Error in transaction because $@\n ";
138             }
139              
140 1         32 $this->{dbconn}->{AutoCommit} = 1;
141              
142 1         19 return $result;
143             }
144              
145             # }}}
146             # {{{ exec Execute an query
147             #
148             # You can pass bind array as arguments.
149             #
150             sub exec {
151 36     36 1 144 my $this = shift;
152 36         91 my $query = shift;
153 36         86 my @bind = @_;
154 36         103 my $type = get_sql_type($query);
155 36         59 my $sth;
156             my $rv;
157              
158 36         80 $last_rowid = undef;
159 36         53 $affected_rows = 0;
160              
161 36 50       261 if (!defined $this->{dbconn}) {
162 0         0 $this->{dberror} = __PACKAGE__."::exec_query - DB handle not defined";
163 0         0 return 0;
164             }
165              
166 36         340 $sth = $this->{dbconn}->prepare($query);
167 36 100       6305 return 0 if ($this->check_error(__PACKAGE__."::exec_query - Error while preparing :"));
168              
169 34         1612633 $rv = $sth->execute(@bind);
170 34 100       346 return 0 if ($this->check_error(__PACKAGE__."::exec_query - Error while executing :"));
171              
172 31 100       387 $last_rowid = $this->{dbconn}->func('last_insert_rowid') if ($type == INSERT);
173              
174 31 100 66     256 if (($type == DELETE || $type == UPDATE) && $rv != 0E0) {
      66        
175 1         5 $affected_rows = $rv;
176             }
177              
178 31         203 $sth->finish;
179              
180 31         1531 return 1;
181             }
182             # }}}
183             # {{{ last_insert_rowid Returns the last inserted row id
184             #
185             sub last_insert_rowid {
186 0     0 0 0 return $last_rowid;
187             }
188             # }}}
189             # {{{ get_affected_rows Returns the number of affected rows from last exec
190             #
191             sub get_affected_rows {
192 1     1 0 7 return $affected_rows;
193             }
194             # }}}
195             # {{{ select Execute an select query
196             #
197             # You can pass bind arguments.
198             #
199             sub select {
200 9     9 1 292 my $this = shift;
201 9         19 my $query = shift;
202 9         17 my $funcptr = shift;
203 9         17 my @bind = @_;
204 9         16 my $sth;
205              
206 9 50       49 if (!defined $this->{dbconn}) {
207 0         0 $this->{dberror} = __PACKAGE__."::select_query - DB handle not defined";
208 0         0 return 0;
209             }
210              
211 9         101 $sth = $this->{dbconn}->prepare($query);
212 9 100       1511 return 0 if ($this->check_error(__PACKAGE__."::select_query - Error while preparing :"));
213              
214 8         1145 $sth->execute(@bind);
215 8 50       35 return 0 if ($this->check_error(__PACKAGE__."::select_query - Error while executing :"));
216              
217 8 50       38 $funcptr->($sth) if (defined $funcptr);
218              
219 8         2637 $sth->finish;
220              
221 8         133 return 1;
222             }
223             # }}}
224             # {{{ select_one_row Execute an select query returnin only one row as an hash
225             #
226             sub select_one_row {
227 4     4 1 697 my $this = shift;
228 4         8 my $query = shift;
229 4         10 my @bind = @_;
230 4         9 my $result = undef;
231              
232             $this->select($query,
233 4 50   4   16 sub { my $sth = (defined $_[0]) ? shift : return;
234 4   50     135 $result = $sth->fetchrow_hashref || return;},
235 4         43 @bind);
236              
237 4         28 return $result;
238             }
239             # }}}
240             # {{{ get_dblist Returns an array representing the resultset
241             #
242             # Each result contains key and value
243             #
244             sub get_dblist {
245 1     1 1 4 my $this = shift;
246 1         2 my $query = shift;
247 1         2 my $displayfield = shift;
248 1         2 my $keyfield = shift;
249 1         3 my $result = [];
250 1         3 my $id = 0;
251 1         3 my $sth;
252              
253 1 50       4 if (!defined $this->{dbconn}) {
254 0         0 $this->{dberror} = __PACKAGE__."::get_dblist - DB handle not defined";
255 0         0 return 0;
256             }
257              
258 1         13 $sth = $this->{dbconn}->prepare($query);
259 1 50       137 return 0 if ($this->check_error(__PACKAGE__."::get_dblist - Error while preparing :"));
260              
261 1         128 $sth->execute;
262 1 50       6 return 0 if ($this->check_error(__PACKAGE__."::get_dblist - Error while executing :"));
263              
264 1         49 while (my $data = $sth->fetchrow_hashref) { # Go through the records
265 3         12 $result->[$id]->{id} = $$data{$keyfield};
266 3         11 $result->[$id]->{value} = $$data{$displayfield};
267 3         68 $id++;
268             }
269              
270 1         6 $sth->finish;
271              
272 1         17 return $result;
273             }
274             # }}}
275             # {{{ get_error Return last db error
276             #
277             sub get_error {
278 0     0 1 0 my $this = shift;
279              
280 0         0 return $this->{dberror};
281             }
282             # }}}
283             # {{{ check_error Check if an error occured
284             #
285             # Save the error in dberror var.
286             #
287             sub check_error {
288 96     96 1 202 my $this = shift;
289 96         173 my $err_id = shift;
290 96         418 my $query = shift;
291              
292 96 100 66     1528 if ($DBI::err || $DBI::errstr) {
293 6         24 $this->{dberror} = $err_id."\n";
294 6 50       23 $this->{dberror} .= "SQL : ".$query."\n" if (defined $query);
295 6         61 $this->{dberror} .= "Errors: $DBI::err, $DBI::errstr\n";
296 6         19 push @transaction_errors,$this->{dberror};
297 6         74 return 1;
298             }
299              
300 90         444 return 0;
301             }
302             # }}}
303             # {{{ get_sql_type Get the type of an sql statment
304             #
305             sub get_sql_type {
306 36 50   36 1 135 my $this = (ref $_[0]) ? shift : undef;
307 36         72 my $query = shift;
308              
309 36 50       257 return SELECT if ($query =~ /^\s*SeLeCt/i);
310 36 100       231 return INSERT if ($query =~ /^\s*InSeRt/i);
311 9 50       44 return UPDATE if ($query =~ /^\s*UpDaTe/i);
312 9 100       43 return DELETE if ($query =~ /^\s*DeLeTe/i);
313 8 100       70 return CREATE if ($query =~ /^\s*CrEaTe/i);
314 1 50       5 return DROP if ($query =~ /^\s*DrOp/i);
315              
316 1         2 return INVALID;
317             }
318             # }}}
319              
320             1;
321              
322             # {{{ module documentation
323              
324             __END__