File Coverage

blib/lib/XML/RSS/TimingBotDBI.pm
Criterion Covered Total %
statement 10 95 10.5
branch 1 28 3.5
condition 0 8 0.0
subroutine 4 19 21.0
pod 7 8 87.5
total 22 158 13.9


line stmt bran cond sub pod time code
1              
2             package XML::RSS::TimingBotDBI;
3             $VERSION = '2.01';
4 1     1   6289 use XML::RSS::TimingBot ();
  1         74546  
  1         41  
5             @ISA = ('XML::RSS::TimingBot');
6 1     1   12 use Carp ();
  1         2  
  1         17  
7 1     1   5 use strict;
  1         8  
  1         64  
8              
9 1 50   1   1689 BEGIN { *DEBUG = sub () {0} unless defined &DEBUG }
10              
11             die "Where's _elem?!!?" unless __PACKAGE__->can('_elem');
12             #--------------------------------------------------------------------------
13             # Some accessors:
14              
15 0     0 1   sub rssagent_dbh { shift->_elem('rssdbi_dbh' , @_) }
16 0     0 1   sub rssagent_table { shift->_elem('rssdbi_table', @_) }
17 0     0 1   sub rssagent_url_field { shift->_elem('rssdbi_url_field', @_) }
18 0     0 1   sub rssagent_lastmod_field { shift->_elem('rssdbi_lastmod_field', @_) }
19 0     0 1   sub rssagent_nextupdate_field { shift->_elem('rssdbi_rssagent_nextupdate_field', @_) }
20 0     0 1   sub rssagent_etag_field { shift->_elem('rssdbi_rssagent_etag_field', @_) }
21              
22             #==========================================================================
23              
24             sub _rssagent_init {
25 0     0     my $self = shift;
26 0           $self->SUPER::_rssagent_init(@_);
27              
28             # set some sane values
29 0           $self->rssagent_table('rsstibot');
30 0           $self->rssagent_url_field('feedurl');
31 0           $self->rssagent_lastmod_field('lastmod');
32 0           $self->rssagent_nextupdate_field('nextup');
33 0           $self->rssagent_etag_field('etag');
34 0           return;
35             }
36              
37             sub _assert_dbh {
38 0     0     my $dbh = shift->rssagent_dbh;
39 0 0         return $dbh if $dbh;
40 0           Carp::confess("Set \$feedbot->rssagent_dbh( \$some_dbi_object ) first!");
41             }
42              
43             #--------------------------------------------------------------------------
44              
45              
46             sub datum_from_db {
47 0     0 0   my($self, $url, $varname) = @_;
48              
49 0           my $table = $self->rssagent_table;
50 0           my $furl = $self->rssagent_url_field;
51 0 0         my $fieldname =
    0          
    0          
52             $varname eq 'lastmodified' ? $self->rssagent_lastmod_field
53             : $varname eq 'nextupdate' ? $self->rssagent_nextupdate_field
54             : $varname eq 'etag' ? $self->rssagent_etag_field
55             : die "I don't know how to turn \"$varname\" into a fieldname!\nAborting";
56            
57 0           my $sql = "select $fieldname from $table where $furl = ?"; # binary
58 0           DEBUG and print " DB: $sql => $url\n";
59 0           my $dbh = $self->_assert_dbh;
60 0           $dbh->do("lock tables $table read");
61 0           my($val) = $dbh->selectrow_array($sql, undef, $url);
62 0           $dbh->do("unlock tables;");
63 0           return $val;
64             }
65              
66             sub commit {
67 0     0 1   my $self = shift;
68 0   0       my $for_db = $self->{'rsstimingbot_for_db'} || return;
69 0           DEBUG > 1 and print " I see ", scalar(keys %$for_db), " url-data in $self to save\n";
70 0 0         return unless keys %$for_db;
71              
72 0           my $table = $self->rssagent_table;
73              
74 0           my $dbh = $self->_assert_dbh;
75 0           $self->_make_table_exist($dbh, $table);
76 0           $dbh->do("lock tables $table write");
77              
78 0           $self->_dump_dirty_cache_to_db(
79             $for_db, $dbh,
80             $self->_make_sql_statements( $dbh, $table )
81             );
82              
83 0           $dbh->commit;
84 0           $dbh->do("unlock tables");
85              
86 0           DEBUG > 4 and print "Done committing.\n";
87 0           $self->{'rsstimingbot_for_db'} = {};
88 0           return;
89             }
90              
91             #--------------------------------------------------------------------------
92              
93             sub _dump_dirty_cache_to_db {
94 0     0     my($self, $hoh, $dbh, $action2statement) = @_;
95              
96 0           my($for_this_url, $value, $retval);
97 0           foreach my $url (sort keys %$hoh) {
98 0   0       $for_this_url = $hoh->{$url} || next;
99 0           DEBUG > 4 and print " Vars for $url : ", join(' ', sort keys %$for_this_url), "\n";
100             Var:
101 0           foreach my $varname (sort keys %$for_this_url) {
102 0           $value = $for_this_url->{$varname};
103 0 0         $value = '' unless defined $value;
104 0           DEBUG > 5 and print " Saving $url 's $varname = \"$value\"\n";
105 0           foreach my $action ('update', 'insert') {
106 0 0         Carp::confess "No handler for $varname?!"
107             unless $action2statement->{$action}{$varname};
108 0           $retval = $action2statement->{$action}{$varname}->execute( $value,$url );
109 0 0 0       Carp::confess "Couldn't find a way to $action $varname=$value for $url\nReason: ",
110             $dbh->err||"??", "\nAborting"
111             unless $retval; # i.e., if it dies
112 0 0         next Var unless $retval == 0; # i.e., unless it affected no rows
113             }
114 0           Carp::confess "Couldn't find a way to update/insert $varname=$value ?!";
115             }
116             }
117 0           return;
118             }
119              
120             #--------------------------------------------------------------------------
121              
122             sub _make_sql_statements {
123 0     0     my($self, $dbh, $table) = @_;
124              
125 0           my $furl = $self->rssagent_url_field;
126 0           my %action2statement;
127              
128             my $sql;
129 0           for my $equiv (
130             [ 'lastmodified' => $self->rssagent_lastmod_field ],
131             [ 'nextupdate' => $self->rssagent_nextupdate_field ],
132             [ 'etag' => $self->rssagent_etag_field ],
133             ) {
134 0           for my $way (
135             [ 'update' => "update $table set $$equiv[1] = ? where $furl = ?" ],
136             [ 'insert' => "insert into $table ($$equiv[1], $furl) values (?,?)" ],
137             ) {
138 0           $sql = $way->[1];
139 0   0       $action2statement{ $way->[0] }{ $$equiv[0] } = $dbh->prepare( $sql )
140             || die "Couldn't prepare an $$way[0] statement for $$equiv[0]: ".($dbh->err||"??");
141 0           DEBUG > 6 and print "# $$equiv[0] updater: $sql\n";
142             }
143             }
144 0           return \%action2statement;
145             }
146              
147             #--------------------------------------------------------------------------
148              
149             sub _make_table_exist {
150 0     0     my($self, $dbh, $table) = @_ ;
151              
152 0 0         return 1 if $self->{'rssagent_dbh_exists'}{$table};
153              
154 0           my $furl = $self->rssagent_url_field;
155 0           my $flastmod = $self->rssagent_lastmod_field;
156 0           my $fnextupdate = $self->rssagent_nextupdate_field;
157 0           my $fetag = $self->rssagent_etag_field;
158              
159 0           foreach my $method (
160             '_create_table_if_not_exists', '_just_create_table',
161             ) {
162 0 0         next unless $self->$method(
163             $dbh, $table, $furl, $fnextupdate, $flastmod, $fetag
164             );
165 0           DEBUG > 7 and print " DB: $method worked.\n";
166 0           $self->{'rssagent_dbh_exists'}{$table} = 1;
167 0           return;
168             }
169 0           Carp::confess "I don't know how to make table $table for $dbh and $self!\nAborting";
170             }
171              
172             sub _create_table_if_not_exists {
173 0     0     my($self, $dbh, $table, $furl, $fnextupdate, $flastmod, $fetag) = @_ ;
174 0 0         return 1 if $dbh->do(qq<
175             create table if not exists
176             $table (
177             $furl varchar(255) not null primary key,
178             $fnextupdate int(11),
179             $flastmod varchar(40),
180             $fetag varchar(250)
181             )
182             >);
183 0           return 0;
184             }
185              
186             sub _just_create_table { # keep it real simple...
187 0     0     my($self, $dbh, $table, $furl, $fnextupdate, $flastmod, $fetag) = @_ ;
188 0 0         return 1 if $dbh->do(qq<
189             create table
190             $table (
191             $furl varchar(255) not null primary key,
192             $fnextupdate int(11),
193             $flastmod varchar(40),
194             $fetag varchar(250)
195             )
196             >);
197 0           return 0;
198             }
199              
200             #--------------------------------------------------------------------------
201              
202             1;
203             __END__