File Coverage

blib/lib/CPAN/SQLite/DBI/Search.pm
Criterion Covered Total %
statement 180 197 91.3
branch 69 92 75.0
condition 10 17 58.8
subroutine 21 21 100.0
pod 2 4 50.0
total 282 331 85.2


line stmt bran cond sub pod time code
1             # $Id: Search.pm 84 2020-05-31 06:29:34Z stro $
2              
3             package CPAN::SQLite::DBI::Search;
4              
5 5     5   39 use strict;
  5         15  
  5         165  
6 5     5   28 use warnings;
  5         26  
  5         520  
7              
8             BEGIN {
9 5     5   29 our $VERSION = '0.219';
10 5         10 $CPAN::SQLite::DBI::Search::info::VERSION = $VERSION;
11 5         11 $CPAN::SQLite::DBI::Search::mods::VERSION = $VERSION;
12 5         49 $CPAN::SQLite::DBI::Search::dists::VERSION = $VERSION;
13 5         161 $CPAN::SQLite::DBI::Search::auths::VERSION = $VERSION;
14             }
15              
16 5     5   36 use parent 'CPAN::SQLite::DBI';
  5         14  
  5         69  
17 5     5   331 use CPAN::SQLite::DBI qw($tables $dbh);
  5         11  
  5         667  
18 5     5   38 use CPAN::SQLite::Util qw($full_id);
  5         12  
  5         432  
19              
20             package CPAN::SQLite::DBI::Search::info;
21 5     5   33 use parent 'CPAN::SQLite::DBI::Search';
  5         19  
  5         21  
22 5     5   329 use CPAN::SQLite::DBI qw($dbh);
  5         19  
  5         485  
23              
24             package CPAN::SQLite::DBI::Search::mods;
25 5     5   39 use parent 'CPAN::SQLite::DBI::Search';
  5         12  
  5         35  
26 5     5   337 use CPAN::SQLite::DBI qw($dbh);
  5         13  
  5         505  
27              
28             package CPAN::SQLite::DBI::Search::dists;
29 5     5   41 use parent 'CPAN::SQLite::DBI::Search';
  5         15  
  5         37  
30 5     5   331 use CPAN::SQLite::DBI qw($dbh);
  5         11  
  5         460  
31              
32             package CPAN::SQLite::DBI::Search::auths;
33 5     5   36 use parent 'CPAN::SQLite::DBI::Search';
  5         16  
  5         20  
34 5     5   374 use CPAN::SQLite::DBI qw($dbh);
  5         11  
  5         479  
35              
36             package CPAN::SQLite::DBI::Search;
37 5     5   46 use parent 'CPAN::SQLite::DBI';
  5         22  
  5         39  
38 5     5   494 use CPAN::SQLite::DBI qw($tables $dbh);
  5         11  
  5         453  
39 5     5   35 use CPAN::SQLite::Util qw($full_id download);
  5         11  
  5         8939  
40              
41             sub fetch {
42 871     871 1 3155 my ($self, %args) = @_;
43 871         1581 my $fields = $args{fields};
44 871         1242 my $search = $args{search};
45 871 50       2104 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  871         2515  
46 871 50       2657 my $sql = $self->sql_statement(%args) or do {
47 0         0 $self->{error} = 'Error constructing sql statement: ' . $self->{error};
48 0         0 return;
49             };
50 871 50       5754 my $sth = $dbh->prepare($sql) or do {
51 0         0 $self->db_error();
52 0         0 return;
53             };
54 871 50       195781 $sth->execute() or do {
55 0         0 $self->db_error($sth);
56 0         0 return;
57             };
58              
59 871 100       10959 if (not $search->{wantarray}) {
60 646         1189 my (%results, $results);
61 646         11855 @results{@fields} = $sth->fetchrow_array;
62 646 100       3008 $results = ($sth->rows == 0) ? undef : \%results;
63 646         2406 $sth->finish;
64 646         8649 undef $sth;
65 646 100       2707 $self->extra_info($results) if $results;
66 646         4248 return $results;
67             } else {
68 225         402 my (%hash, $results);
69 225         2100 while (@hash{@fields} = $sth->fetchrow_array) {
70 2191         11460 my %tmp = %hash;
71 2191         6039 $self->extra_info(\%tmp);
72 2191         3178 push @{$results}, \%tmp;
  2191         14862  
73             }
74 225 100       920 $results = undef if ($sth->rows == 0);
75 225         648 $sth->finish;
76 225         2096 undef $sth;
77 225         1443 return $results;
78             }
79             }
80              
81             sub fetch_and_set {
82 1942     1942 0 7561 my ($self, %args) = @_;
83 1942         3272 my $fields = $args{fields};
84 1942         2951 my $search = $args{search};
85 1942         2762 my $meta_obj = $args{meta_obj};
86 1942 50 33     11377 die "Please supply a CPAN::SQLite::Meta::* object"
87             unless ($meta_obj and ref($meta_obj) =~ /^CPAN::SQLite::META/);
88 1942 50       4971 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  1942         5365  
89 1942 50       6127 my $sql = $self->sql_statement(%args) or do {
90 0         0 $self->{error} = 'Error constructing sql statement: ' . $self->{error};
91 0         0 return;
92             };
93 1942 50       11981 my $sth = $dbh->prepare($sql) or do {
94 0         0 $self->db_error();
95 0         0 return;
96             };
97 1942 50       384907 $sth->execute() or do {
98 0         0 $self->db_error($sth);
99 0         0 return;
100             };
101              
102 1942         12663 my $want_ids = $args{want_ids};
103 1942         3179 my $set_list = $args{set_list};
104 1942         3370 my $download = $args{download};
105 1942 100       4950 if (not $search->{wantarray}) {
106 921         1650 my (%results, %meta_results, $results);
107 921         16472 @results{@fields} = $sth->fetchrow_array;
108 921 100       4368 $results = ($sth->rows == 0) ? undef : \%results;
109 921         3414 $sth->finish;
110 921         12892 undef $sth;
111 921 100       2496 return unless $results;
112 913         2598 $self->extra_info($results);
113 913         3459 $meta_obj->set_data($results);
114              
115 913 100       22170 if ($want_ids) {
116 907         2466 $meta_results{dist_id} = $results{dist_id};
117 907         2561 $meta_results{download} = download($results{cpanid}, $results{dist_file});
118 907         7642 return \%meta_results;
119             } else {
120 6         47 return 1;
121             }
122             } else {
123 1021         1878 my (%hash, $meta_results);
124 1021         9321 while (@hash{@fields} = $sth->fetchrow_array) {
125 23080         63688 my %tmp = %hash;
126 23080 100       41303 if ($set_list) {
127 22772         28082 push @{$meta_results}, \%tmp;
  22772         108538  
128             } else {
129 308         895 $self->extra_info(\%tmp);
130 308         986 $meta_obj->set_data(\%tmp);
131 308 100       7573 if ($want_ids) {
132 298         835 my $download = download($tmp{cpanid}, $tmp{dist_file});
133 298         4454 push @{$meta_results},
134             {
135             dist_id => $tmp{dist_id},
136 298         470 download => $download
137             };
138              
139             }
140             }
141             }
142 1021 100       4279 $meta_results = undef if ($sth->rows == 0);
143 1021         3218 $sth->finish;
144 1021         10274 undef $sth;
145 1021 100       2866 return unless $meta_results;
146 1011 100       4697 $meta_obj->set_list_data($meta_results, $download) if $set_list;
147 1011 100       13923 return $want_ids ? $meta_results : 1;
148             }
149             }
150              
151             sub extra_info {
152 4052     4052 0 7277 my ($self, $results) = @_;
153 4052 100 100     12921 if ($results->{cpanid} and $results->{dist_file}) {
154 2552         7935 $results->{download} = download($results->{cpanid}, $results->{dist_file});
155             }
156 4052         7239 return;
157             }
158              
159             sub sql_statement {
160 2813     2813 1 8728 my ($self, %args) = @_;
161              
162 2813         4644 my $search = $args{search};
163 2813 100       5855 my $distinct = $search->{distinct} ? 'DISTINCT' : '';
164 2813         4504 my $table = $args{table};
165              
166 2813         3997 my $fields = $args{fields};
167 2813 50       5139 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  2813         6807  
168 2813         5639 for (@fields) {
169 22623 100       44068 $_ = $full_id->{$_} if $full_id->{$_};
170             }
171              
172 2813         10243 my $sql = qq{SELECT $distinct } . join(',', @fields);
173 2813         4378 my $where = '';
174 2813         4582 my $type = $search->{type};
175             QUERY: {
176 2813 100       4083 ($type eq 'query') and do {
  2813         5940  
177 38         92 my $value = $search->{value};
178 38 50       92 last QUERY if ($value eq '^');
179 38         68 my $name = $search->{name};
180 38         64 my $text = $search->{text};
181 38 100       198 my $use_like = ($value =~ /^\^?[A-Za-z0-9_\\\:\-]+$/) ? 1 : 0;
182 38         75 my $prepend = '%';
183 38 100 100     190 if ($use_like and $value =~ /^\^/) {
184 4         9 $prepend = '';
185 4         18 $value =~ s/^\^//;
186 4         9 $value =~ s{\\}{}g;
187             }
188             $where =
189 38 100       150 $use_like
190             ? qq{$name LIKE '$prepend$value%'}
191             : qq{$name REGEXP '(?i:$value)'};
192              
193 38 100       90 if ($name eq 'cpanid') {
194 10 100       59 $where .=
195             $use_like
196             ? qq{ OR $text LIKE '$prepend$value%'}
197             : qq{ OR $text REGEXP '(?i:$value)'};
198             }
199 38         88 last QUERY;
200             };
201 2775 100       5162 ($type eq 'id') and do {
202 1208         3011 $where = qq{ $search->{id} = $search->{value} };
203 1208         2362 last QUERY;
204             };
205 1567 50       3203 ($type eq 'name') and do {
206 1567         3704 $where = qq{ $search->{name} = '$search->{value}' };
207 1567         2633 last QUERY;
208             };
209 0         0 warn qq{Unknown query type};
210 0         0 return;
211             }
212 2813         3801 my $join;
213              
214 2813         7486 $sql .= ' FROM ' . $table;
215 2813   66     7795 my $left_join = $args{join} || $args{left_join};
216 2813 100       5383 if ($left_join) {
217 1579 50       3369 if (ref($left_join) eq 'HASH') {
218 1579         4261 foreach my $key (keys %$left_join) {
219 3052         4709 my $id = $left_join->{$key};
220 3052         9126 $sql .= " LEFT JOIN $key ON $table.$id=$key.$id ";
221             }
222             }
223             }
224              
225 2813 50       5749 if ($where) {
226 2813         5960 $sql .= ' WHERE ( ' . $where . ' )';
227 2813 50       5419 $sql .= ' AND (' . $join . ')' if $join;
228             } else {
229 0 0       0 $sql .= ' WHERE (' . $join . ')' if $join;
230             }
231              
232 2813         4397 my $order_by = '';
233 2813 50       5698 if (my $user_order_by = $args{order_by}) {
234 2813 50       5493 $order_by = $order_by ? "$order_by,$user_order_by" : $user_order_by;
235             }
236 2813 50 33     9005 if ($order_by and $where) {
237 2813         5405 $sql .= qq{ ORDER BY $order_by };
238             }
239              
240 2813 50       5873 if (my $limit = $args{limit}) {
241             my ($min, $max) =
242             ref($limit) eq 'HASH'
243             ? ($limit->{min} || 0, $limit->{max})
244 0 0 0     0 : (0, $limit);
245 0         0 $sql .= qq{ LIMIT $min,$max };
246             }
247 2813         12179 return $sql;
248             }
249              
250             1;
251              
252             =head1 NAME
253              
254             CPAN::SQLite::DBI::Search - DBI information for searching the CPAN::SQLite database
255              
256             =head1 VERSION
257              
258             version 0.219
259              
260             =head1 DESCRIPTION
261              
262             This module provides methods for L for searching
263             the C database. There are two main methods.
264              
265             =over
266              
267             =item C
268              
269             This takes information from C and sets up
270             a query on the database, returning the results found.
271              
272             =item C
273              
274             This is used by the C method to construct the appropriate
275             SQL statement.
276              
277             =back
278              
279             =head1 SEE ALSO
280              
281             L
282              
283             =cut