File Coverage

blib/lib/Purple/SQLite.pm
Criterion Covered Total %
statement 61 64 95.3
branch 4 12 33.3
condition 1 3 33.3
subroutine 11 11 100.0
pod 5 5 100.0
total 82 95 86.3


line stmt bran cond sub pod time code
1             package Purple::SQLite;
2              
3 1     1   5 use strict;
  1         2  
  1         30  
4 1     1   9191 use DBI;
  1         24755  
  1         79  
5 1     1   784 use Purple::Sequence;
  1         3  
  1         1025  
6              
7             our $VERSION = '0.9';
8              
9             my $DEFAULT_DB_LOC = 'purple.db';
10             # XXX not positive we want url to NOT NULL
11             # XXX last_nid table is for speed handling
12             my $CREATE_SQL1 = q{
13             CREATE TABLE nids (
14             nid TEXT PRIMARY KEY NOT NULL,
15             url TEXT NOT NULL,
16             created_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
17             updated_on TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
18             );
19             };
20             my $CREATE_SQL2 = q{
21             CREATE TABLE lastnid (
22             nid TEXT NOT NULL
23             );
24             };
25             my $CREATE_SQL3 = q{
26             INSERT INTO lastnid (nid) VALUES ('0');
27             };
28              
29             sub _New {
30 2     2   6 my $class = shift;
31 2         23 my %p = @_;
32 2         5 my $self;
33              
34             my $db_loc;
35 2 50       13 if ($p{store}) {
36 2         11 $db_loc = $p{store} . '/' . $DEFAULT_DB_LOC;
37             }
38 2   33     7 $db_loc ||= $DEFAULT_DB_LOC;
39              
40 2         12 $self->{db_loc} = $db_loc;
41              
42 2         52 $self->{dbh} = DBI->connect("dbi:SQLite:$db_loc", undef, undef);
43             # { AutoCommit => 0 });
44              
45             # create nids table if it doesn't already exist
46 2 50       15662 if (!_table_exists($self->{dbh}, 'nids')) {
47 2         15 $self->{dbh}->do($CREATE_SQL1);
48 2         1452287 $self->{dbh}->do($CREATE_SQL2);
49 2         120398 $self->{dbh}->do($CREATE_SQL3);
50             }
51 2         597584 bless($self, $class);
52             }
53              
54             # XXX retrieving the lastnid is slow
55             # using max does not work when the nids are mixed numbers and letters
56             # last_row_id (see DBD::SQLite) was tested as well as the below,
57             # neither is great
58             sub getNext {
59 1     1 1 13 my ($self, $url) = @_;
60              
61 1         21 $self->{dbh}->do('BEGIN TRANSACTION');
62             # get next NID
63 1         131 my $sth = $self->{dbh}->prepare('SELECT nid FROM lastnid');
64 1         217 $sth->execute();
65 1         23 my $currentNid = ($sth->fetchrow_array)[0];
66 1         8 my $nextNid = Purple::Sequence::increment_nid($currentNid);
67             # update NID->URL value
68 1         10 $self->{dbh}->do("INSERT INTO nids (nid, url) VALUES ('$nextNid', '$url')");
69 1         359 $self->{dbh}->do("UPDATE lastnid SET nid = '$nextNid'");
70 1         128 $self->{dbh}->do('COMMIT TRANSACTION');
71              
72 1         22339 return $nextNid;
73             }
74              
75             sub getURL {
76 1     1 1 1060 my ($self, $nid) = @_;
77 1         11 my $sth = $self->{dbh}->prepare('SELECT url FROM nids WHERE nid = ?');
78 1         236 $sth->execute($nid);
79 1         84 return ($sth->fetchrow_array)[0];
80             }
81              
82             sub updateURL {
83 1     1 1 648 my ($self, $url, @nids) = @_;
84 1         7 my $questionMarks = join(', ', map('?', @nids));
85              
86 1         7 $self->{dbh}->do(qq{
87             UPDATE nids SET url = ?, updated_on = ? WHERE nid IN ($questionMarks)
88             }, undef, $url, &_timestamp, @nids);
89             }
90              
91             sub getNIDs {
92 1     1 1 1150 my ($self, $url) = @_;
93              
94 1         24 my $sth = $self->{dbh}->prepare('SELECT nid FROM nids WHERE url = ?');
95 1         402 $sth->execute($url);
96              
97 1         4 my @nids;
98 1         42 while (my $nid = $sth->fetchrow_array) {
99 1         9 push @nids, $nid;
100             }
101 1         23 return @nids;
102             }
103              
104             sub deleteNIDs {
105 1     1 1 14849 my ($self, @nids) = @_;
106 1         13 my $questionMarks = join(', ', map('?', @nids));
107              
108 1         22 $self->{dbh}->do("DELETE FROM nids WHERE nid IN ($questionMarks)",
109             undef, @nids);
110             }
111              
112             ### private
113              
114             sub _timestamp {
115 1     1   46 my @timestamp = localtime;
116 1         20 return sprintf('%d-%02d-%02d %02d:%02d:%02d', $timestamp[5] + 1900,
117             $timestamp[4] + 1, $timestamp[3], $timestamp[2],
118             $timestamp[1], $timestamp[0]);
119             }
120              
121             # stolen from
122             # http://gmax.oltrelinux.com/dbirecipes.html#checking_for_an_existing_table
123             sub _table_exists {
124 2     2   5 my $dbh = shift;
125 2         5 my $table = shift;
126 2         46 my @tables = $dbh->tables('','','','TABLE');
127 2 50       1913 if (@tables) {
128 0         0 for (@tables) {
129 0 0       0 next unless $_;
130 0 0       0 return 1 if $_ eq $table
131             }
132             }
133             else {
134 2         7 eval {
135 2         62 local $dbh->{PrintError} = 0;
136 2         25 local $dbh->{RaiseError} = 1;
137 2         23 $dbh->do(qq{SELECT * FROM $table WHERE 1 = 0 });
138             };
139 2 50       416 return 1 unless $@;
140             }
141 2         10 return 0;
142             }
143              
144             ### fini
145              
146             =head1 NAME
147              
148             Purple::SQLite - SQLite driver for Purple
149              
150             =head1 VERSION
151              
152             Version 0.9
153              
154             =head1 SYNOPSIS
155              
156             SQLite backend for storing and retrieving Purple nids.
157              
158             use Purple::SQLite;
159              
160             my $p = Purple::SQLite->new('purple.db');
161             my $nid = $p->getNext('http://i.love.purple/');
162             my $url = $p->getURL($nid); # http://i.love.purple/
163              
164             =head1 METHODS
165              
166             =head2 new($db_loc)
167              
168             Initializes NID database at $db_loc, creating it if it does not
169             already exist. Defaults to "purple.db" in the current directory if
170             $db_loc is not specified.
171              
172             =head2 getNext($url)
173              
174             Gets the next available NID, assigning it $url in the database.
175              
176             =head2 getURL($nid)
177              
178             Gets the URL associated with NID $nid.
179              
180             =head2 updateURL($url, @nids)
181              
182             Updates the NIDs in @nids with the URL $url.
183              
184             =head2 getNIDs($url)
185              
186             Gets all NIDs associated with $url.
187              
188             =head2 deleteNIDs(@nids)
189              
190             Deletes all NIDs in @nids.
191              
192             =head1 AUTHORS
193              
194             Chris Dent, Ecdent@burningchrome.comE
195              
196             Eugene Eric Kim, Eeekim@blueoxen.comE
197              
198             =head1 BUGS
199              
200             Please report any bugs or feature requests to
201             C, or through the web interface at
202             L.
203             I will be notified, and then you'll automatically be notified of progress on
204             your bug as I make changes.
205              
206             =head1 ACKNOWLEDGEMENTS
207              
208             Thanks to Geraldine's and El Sombrero in Seattle for sustaining us
209             while we coded away. In particular, Eugene would not have made it had
210             it not been for that macho margarita.
211              
212             =head1 COPYRIGHT & LICENSE
213              
214             (C) Copyright 2006 Blue Oxen Associates. All rights reserved.
215              
216             This program is free software; you can redistribute it and/or modify it
217             under the same terms as Perl itself.
218              
219             =cut
220              
221             1; # End of Purple::SQLite