File Coverage

blib/lib/CPAN/SQLite/State.pm
Criterion Covered Total %
statement 48 249 19.2
branch 0 82 0.0
condition 0 18 0.0
subroutine 16 31 51.6
pod 1 4 25.0
total 65 384 16.9


line stmt bran cond sub pod time code
1             # $Id: State.pm 85 2022-10-29 05:44:36Z stro $
2              
3             package CPAN::SQLite::State;
4 3     3   22 use strict;
  3         6  
  3         105  
5 3     3   15 use warnings;
  3         6  
  3         84  
6 3     3   14 no warnings qw(redefine);
  3         6  
  3         163  
7              
8             our $VERSION = '0.220';
9              
10 3     3   16 use English qw/-no_match_vars/;
  3         6  
  3         17  
11              
12 3     3   2273 use CPAN::SQLite::DBI qw($dbh);
  3         10  
  3         388  
13 3     3   1590 use CPAN::SQLite::DBI::Index;
  3         35  
  3         155  
14 3     3   21 use CPAN::SQLite::Util qw(has_hash_data print_debug);
  3         8  
  3         157  
15 3     3   17 use Scalar::Util 'weaken';
  3         6  
  3         2339  
16              
17             my %tbl2obj;
18             $tbl2obj{$_} = __PACKAGE__ . '::' . $_ for (qw(dists mods auths info));
19             my %obj2tbl = reverse %tbl2obj;
20              
21             our $dbh = $CPAN::SQLite::DBI::dbh;
22              
23             sub new {
24 0     0 0   my ($class, %args) = @_;
25              
26 0 0         if ($args{setup}) {
27 0           die "No state information available under setup";
28             }
29              
30 0           my $index = $args{index};
31 0           my @tables = qw(dists mods auths info);
32 0           foreach my $table (@tables) {
33 0           my $obj = $index->{$table};
34 0 0 0       die "Please supply a CPAN::SQLite::Index::$table object"
35             unless ($obj and ref($obj) eq "CPAN::SQLite::Index::$table");
36             }
37 0           my $cdbi = CPAN::SQLite::DBI::Index->new(%args);
38              
39             my $self = {
40             index => $index,
41             obj => {},
42             cdbi => $cdbi,
43             reindex => $args{reindex},
44 0           };
45 0           return bless $self, $class;
46             }
47              
48             sub state {
49 0     0 1   my $self = shift;
50 0 0         unless ($self->create_objs()) {
51 0           print_debug("Cannot create objects");
52 0           return;
53             }
54 0 0         unless ($self->state_info()) {
55 0           print_debug("Getting state information failed");
56 0           return;
57             }
58 0           return 1;
59             }
60              
61             sub create_objs {
62 0     0 0   my $self = shift;
63 0           my @tables = qw(dists auths mods info);
64              
65 0           foreach my $table (@tables) {
66 0           my $obj;
67 0           my $pack = $tbl2obj{$table};
68 0           my $index = $self->{index}->{$table};
69 0 0 0       if ($index and ref($index) eq "CPAN::SQLite::Index::$table") {
70 0           my $info = $index->{info};
71 0 0         if ($table ne 'info') {
72 0 0         return unless has_hash_data($info);
73             }
74             $obj = $pack->new(
75             info => $info,
76 0           cdbi => $self->{cdbi}->{objs}->{$table});
77             } else {
78 0           $obj = $pack->new();
79             }
80 0           $self->{obj}->{$table} = $obj;
81             }
82              
83 0           foreach my $table (@tables) {
84 0           my $obj = $self->{obj}->{$table};
85 0           foreach (@tables) {
86 0 0         next if ref($obj) eq $tbl2obj{$_};
87 0           $obj->{obj}->{$_} = $self->{obj}->{$_};
88 0           weaken $obj->{obj}->{$_};
89             }
90             }
91 0           return 1;
92             }
93              
94             sub state_info {
95 0     0 0   my $self = shift;
96 0           my @methods = qw(ids state);
97 0           my @tables = qw(dists auths mods);
98              
99 0           for my $method (@methods) {
100 0           for my $table (@tables) {
101 0           my $obj = $self->{obj}->{$table};
102 0 0         unless ($obj->$method()) {
103 0 0         if (my $error = $obj->{error_msg}) {
104 0           print_debug("Fatal error from ", ref($obj), ": ", $error, $/);
105 0           return;
106             } else {
107 0           my $info = $obj->{info_msg};
108 0           print_debug("Info from ", ref($obj), ": ", $info, $/);
109             }
110             }
111             }
112             }
113              
114             # Check "info"
115 0 0         if (my $obj = $self->{'obj'}->{'info'}) {
116 0 0         return unless $obj->state;
117             }
118 0           return 1;
119             }
120              
121             package CPAN::SQLite::State::auths;
122 3     3   26 use parent 'CPAN::SQLite::State';
  3         6  
  3         16  
123 3     3   225 use CPAN::SQLite::Util qw(has_hash_data print_debug);
  3         6  
  3         1317  
124              
125             sub new {
126 0     0     my ($class, %args) = @_;
127 0           my $info = $args{info};
128 0 0         die "No author info available" unless has_hash_data($info);
129 0           my $cdbi = $args{cdbi};
130 0 0 0       die "No dbi object available"
131             unless ($cdbi and ref($cdbi) eq 'CPAN::SQLite::DBI::Index::auths');
132 0           my $self = {
133             info => $info,
134             insert => {},
135             update => {},
136             delete => {},
137             ids => {},
138             obj => {},
139             cdbi => $cdbi,
140             error_msg => '',
141             info_msg => '',
142             };
143 0           return bless $self, $class;
144             }
145              
146             sub ids {
147 0     0     my $self = shift;
148 0           my $cdbi = $self->{cdbi};
149 0 0         $self->{ids} = $cdbi->fetch_ids() or do {
150 0           $self->{error_msg} = $cdbi->{error_msg};
151 0           return;
152             };
153 0           return 1;
154             }
155              
156             sub state {
157 0     0     my $self = shift;
158 0           my $auth_ids = $self->{ids};
159 0 0         return unless my $dist_obj = $self->{obj}->{dists};
160 0           my $dist_update = $dist_obj->{update};
161 0           my $dist_insert = $dist_obj->{insert};
162 0           my $dists = $dist_obj->{info};
163 0           my ($update, $insert);
164 0 0         if (has_hash_data($dist_insert)) {
165              
166 0           foreach my $distname (keys %{$dist_insert}) {
  0            
167 0           my $cpanid = $dists->{$distname}->{cpanid};
168 0 0         if (my $auth_id = $auth_ids->{$cpanid}) {
169 0           $update->{$cpanid} = $auth_id;
170             } else {
171 0           $insert->{$cpanid}++;
172             }
173             }
174             }
175 0 0         if (has_hash_data($dist_update)) {
176 0           foreach my $distname (keys %{$dist_update}) {
  0            
177 0           my $cpanid = $dists->{$distname}->{cpanid};
178 0 0         if (my $auth_id = $auth_ids->{$cpanid}) {
179 0           $update->{$cpanid} = $auth_id;
180             } else {
181 0           $insert->{$cpanid}++;
182             }
183             }
184             }
185 0           $self->{update} = $update;
186 0           $self->{insert} = $insert;
187 0           return 1;
188             }
189              
190             package CPAN::SQLite::State::dists;
191 3     3   24 use parent 'CPAN::SQLite::State';
  3         8  
  3         13  
192 3     3   202 use CPAN::SQLite::Util qw(vcmp has_hash_data print_debug);
  3         13  
  3         1717  
193              
194             sub new {
195 0     0     my ($class, %args) = @_;
196 0           my $info = $args{info};
197 0 0         die "No dist info available" unless has_hash_data($info);
198 0           my $cdbi = $args{cdbi};
199 0 0 0       die "No dbi object available"
200             unless ($cdbi and ref($cdbi) eq 'CPAN::SQLite::DBI::Index::dists');
201 0           my $self = {
202             info => $info,
203             insert => {},
204             update => {},
205             delete => {},
206             ids => {},
207             versions => {},
208             obj => {},
209             cdbi => $cdbi,
210             error_msg => '',
211             info_msg => '',
212             reindex => undef,
213             };
214 0           return bless $self, $class;
215             }
216              
217             sub ids {
218 0     0     my $self = shift;
219 0           my $cdbi = $self->{cdbi};
220 0 0         ($self->{ids}, $self->{versions}) = $cdbi->fetch_ids() or do {
221 0           $self->{error_msg} = $cdbi->{error_msg};
222 0           return;
223             };
224 0           return 1;
225             }
226              
227             sub state {
228 0     0     my $self = shift;
229 0           my $dist_versions = $self->{versions};
230 0           my $dists = $self->{info};
231 0           my $dist_ids = $self->{ids};
232 0           my ($insert, $update, $delete);
233              
234 0           my $reindex = $self->{reindex};
235 0 0         if (defined $reindex) {
236 0 0         my @dists = ref($reindex) eq 'ARRAY' ? @$reindex : ($reindex);
237 0           foreach my $distname (@dists) {
238 0           my $id = $dist_ids->{$distname};
239 0 0         if (not defined $id) {
240 0           print_debug(qq{"$distname" does not have an id: reindexing ignored\n});
241 0           next;
242             }
243 0           $update->{$distname} = $id;
244             }
245 0           $self->{update} = $update;
246 0           return 1;
247             }
248              
249 0           foreach my $distname (keys %$dists) {
250 0 0         if (not defined $dist_versions->{$distname}) {
    0          
251 0           $insert->{$distname}++;
252             } elsif (vcmp($dists->{$distname}->{dist_vers}, $dist_versions->{$distname}) > 0) {
253 0           $update->{$distname} = $dist_ids->{$distname};
254             }
255             }
256 0           $self->{update} = $update;
257 0           $self->{insert} = $insert;
258 0           foreach my $distname (keys %$dist_versions) {
259 0 0         next if $dists->{$distname};
260 0           $delete->{$distname} = $dist_ids->{$distname};
261 0           print_debug("Will delete $distname\n");
262             }
263 0           $self->{delete} = $delete;
264 0           return 1;
265             }
266              
267             package CPAN::SQLite::State::mods;
268 3     3   23 use parent 'CPAN::SQLite::State';
  3         6  
  3         13  
269 3     3   230 use CPAN::SQLite::Util qw(has_hash_data print_debug);
  3         8  
  3         2051  
270              
271             sub new {
272 0     0     my ($class, %args) = @_;
273 0           my $info = $args{info};
274 0 0         die "No module info available" unless has_hash_data($info);
275 0           my $cdbi = $args{cdbi};
276 0 0 0       die "No dbi object available"
277             unless ($cdbi and ref($cdbi) eq 'CPAN::SQLite::DBI::Index::mods');
278 0           my $self = {
279             info => $info,
280             insert => {},
281             update => {},
282             delete => {},
283             ids => {},
284             obj => {},
285             cdbi => $cdbi,
286             error_msg => '',
287             info_msg => '',
288             };
289 0           return bless $self, $class;
290             }
291              
292             sub ids {
293 0     0     my $self = shift;
294 0           my $cdbi = $self->{cdbi};
295 0 0         $self->{ids} = $cdbi->fetch_ids() or do {
296 0           $self->{error_msg} = $cdbi->{error_msg};
297 0           return;
298             };
299 0           return 1;
300             }
301              
302             sub state {
303 0     0     my $self = shift;
304 0           my $mod_ids = $self->{ids};
305 0 0         return unless my $dist_obj = $self->{obj}->{dists};
306 0           my $dists = $dist_obj->{info};
307 0           my $dist_update = $dist_obj->{update};
308 0           my $dist_insert = $dist_obj->{insert};
309 0           my ($update, $insert, $delete);
310 0           my $cdbi = $self->{cdbi};
311              
312 0 0         if (has_hash_data($dist_insert)) {
313 0           foreach my $distname (keys %{$dist_insert}) {
  0            
314 0           foreach my $module (keys %{ $dists->{$distname}->{modules} }) {
  0            
315 0           $insert->{$module}++;
316             }
317             }
318             }
319 0 0         if (has_hash_data($dist_update)) {
320 0           foreach my $distname (keys %{$dist_update}) {
  0            
321 0           foreach my $module (keys %{ $dists->{$distname}->{modules} }) {
  0            
322 0           my $mod_id = $mod_ids->{$module};
323 0 0         if ($mod_id) {
324 0           $update->{$module} = $mod_id;
325             } else {
326 0           $insert->{$module}++;
327             }
328             }
329             }
330             }
331              
332 0 0         if (has_hash_data($dist_update)) {
333 0           my $sql = q{SELECT mod_id,mod_name from mods,dists WHERE dists.dist_id = mods.dist_id and dists.dist_id = ?};
334 0 0         my $sth = $dbh->prepare($sql) or do {
335 0           $cdbi->db_error();
336 0           $self->{error_msg} = $cdbi->{error_msg};
337 0           return;
338             };
339 0           my $dist_ids = $dist_obj->{ids};
340 0           foreach my $distname (keys %{$dist_update}) {
  0            
341 0           my %mods = ();
342 0           %mods = map { $_ => 1 } keys %{ $dists->{$distname}->{modules} };
  0            
  0            
343 0 0         $sth->execute($dist_ids->{$distname}) or do {
344 0           $cdbi->db_error($sth);
345 0           $self->{error_msg} = $cdbi->{error_msg};
346 0           return;
347             };
348 0           while (my ($mod_id, $mod_name) = $sth->fetchrow_array) {
349 0 0         next if $mods{$mod_name};
350 0           $delete->{$mod_name} = $mod_id;
351             }
352             }
353 0           $sth->finish;
354 0           undef $sth;
355             }
356              
357 0           $self->{update} = $update;
358 0           $self->{insert} = $insert;
359 0           $self->{delete} = $delete;
360 0           return 1;
361             }
362              
363             package CPAN::SQLite::State::info;
364 3     3   24 use parent 'CPAN::SQLite::State';
  3         16  
  3         92  
365 3     3   236 use CPAN::SQLite::Util qw(has_hash_data print_debug);
  3         8  
  3         591  
366              
367             sub new {
368 0     0     my ($class, %args) = @_;
369 0           my $cdbi = $args{cdbi};
370 0 0 0       die "No dbi object available"
371             unless ($cdbi and ref($cdbi) eq 'CPAN::SQLite::DBI::Index::info');
372 0           my $self = {
373             info => '',
374             insert => {},
375             update => {},
376             delete => {},
377             ids => {},
378             obj => {},
379             cdbi => $cdbi,
380             error_msg => '',
381             info_msg => '',
382             };
383 0           return bless $self, $class;
384             }
385              
386             sub state {
387 0     0     my $self = shift;
388              
389 0           return 1;
390             }
391              
392             package CPAN::SQLite::State;
393              
394             1;
395              
396             __END__