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 85 2022-10-29 05:44:36Z stro $
2              
3             package CPAN::SQLite::DBI::Search;
4              
5 5     5   40 use strict;
  5         17  
  5         157  
6 5     5   32 use warnings;
  5         19  
  5         447  
7              
8             BEGIN {
9 5     5   15 our $VERSION = '0.220';
10 5         13 $CPAN::SQLite::DBI::Search::info::VERSION = $VERSION;
11 5         11 $CPAN::SQLite::DBI::Search::mods::VERSION = $VERSION;
12 5         34 $CPAN::SQLite::DBI::Search::dists::VERSION = $VERSION;
13 5         125 $CPAN::SQLite::DBI::Search::auths::VERSION = $VERSION;
14             }
15              
16 5     5   34 use parent 'CPAN::SQLite::DBI';
  5         16  
  5         47  
17 5     5   307 use CPAN::SQLite::DBI qw($tables $dbh);
  5         21  
  5         585  
18 5     5   36 use CPAN::SQLite::Util qw($full_id);
  5         11  
  5         430  
19              
20             package CPAN::SQLite::DBI::Search::info;
21 5     5   33 use parent 'CPAN::SQLite::DBI::Search';
  5         13  
  5         28  
22 5     5   349 use CPAN::SQLite::DBI qw($dbh);
  5         14  
  5         511  
23              
24             package CPAN::SQLite::DBI::Search::mods;
25 5     5   54 use parent 'CPAN::SQLite::DBI::Search';
  5         12  
  5         24  
26 5     5   363 use CPAN::SQLite::DBI qw($dbh);
  5         13  
  5         440  
27              
28             package CPAN::SQLite::DBI::Search::dists;
29 5     5   37 use parent 'CPAN::SQLite::DBI::Search';
  5         21  
  5         21  
30 5     5   330 use CPAN::SQLite::DBI qw($dbh);
  5         10  
  5         459  
31              
32             package CPAN::SQLite::DBI::Search::auths;
33 5     5   36 use parent 'CPAN::SQLite::DBI::Search';
  5         10  
  5         22  
34 5     5   332 use CPAN::SQLite::DBI qw($dbh);
  5         15  
  5         468  
35              
36             package CPAN::SQLite::DBI::Search;
37 5     5   35 use parent 'CPAN::SQLite::DBI';
  5         23  
  5         45  
38 5     5   432 use CPAN::SQLite::DBI qw($tables $dbh);
  5         11  
  5         419  
39 5     5   36 use CPAN::SQLite::Util qw($full_id download);
  5         14  
  5         8220  
40              
41             sub fetch {
42 871     871 1 3038 my ($self, %args) = @_;
43 871         1581 my $fields = $args{fields};
44 871         1271 my $search = $args{search};
45 871 50       2152 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  871         2398  
46 871 50       2687 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       5864 my $sth = $dbh->prepare($sql) or do {
51 0         0 $self->db_error();
52 0         0 return;
53             };
54 871 50       114688 $sth->execute() or do {
55 0         0 $self->db_error($sth);
56 0         0 return;
57             };
58              
59 871 100       11169 if (not $search->{wantarray}) {
60 646         1665 my (%results, $results);
61 646         12671 @results{@fields} = $sth->fetchrow_array;
62 646 100       3457 $results = ($sth->rows == 0) ? undef : \%results;
63 646         2618 $sth->finish;
64 646         8536 undef $sth;
65 646 100       2947 $self->extra_info($results) if $results;
66 646         3931 return $results;
67             } else {
68 225         440 my (%hash, $results);
69 225         2260 while (@hash{@fields} = $sth->fetchrow_array) {
70 2191         11517 my %tmp = %hash;
71 2191         6648 $self->extra_info(\%tmp);
72 2191         2941 push @{$results}, \%tmp;
  2191         16238  
73             }
74 225 100       853 $results = undef if ($sth->rows == 0);
75 225         661 $sth->finish;
76 225         2181 undef $sth;
77 225         1377 return $results;
78             }
79             }
80              
81             sub fetch_and_set {
82 1942     1942 0 7798 my ($self, %args) = @_;
83 1942         3184 my $fields = $args{fields};
84 1942         2859 my $search = $args{search};
85 1942         2649 my $meta_obj = $args{meta_obj};
86 1942 50 33     11148 die "Please supply a CPAN::SQLite::Meta::* object"
87             unless ($meta_obj and ref($meta_obj) =~ /^CPAN::SQLite::META/);
88 1942 50       4819 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  1942         5471  
89 1942 50       5939 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       12060 my $sth = $dbh->prepare($sql) or do {
94 0         0 $self->db_error();
95 0         0 return;
96             };
97 1942 50       249040 $sth->execute() or do {
98 0         0 $self->db_error($sth);
99 0         0 return;
100             };
101              
102 1942         12520 my $want_ids = $args{want_ids};
103 1942         3315 my $set_list = $args{set_list};
104 1942         3135 my $download = $args{download};
105 1942 100       4870 if (not $search->{wantarray}) {
106 921         1587 my (%results, %meta_results, $results);
107 921         16882 @results{@fields} = $sth->fetchrow_array;
108 921 100       4298 $results = ($sth->rows == 0) ? undef : \%results;
109 921         3676 $sth->finish;
110 921         11921 undef $sth;
111 921 100       2399 return unless $results;
112 913         2479 $self->extra_info($results);
113 913         3289 $meta_obj->set_data($results);
114              
115 913 100       23014 if ($want_ids) {
116 907         2076 $meta_results{dist_id} = $results{dist_id};
117 907         2468 $meta_results{download} = download($results{cpanid}, $results{dist_file});
118 907         7219 return \%meta_results;
119             } else {
120 6         49 return 1;
121             }
122             } else {
123 1021         1763 my (%hash, $meta_results);
124 1021         9879 while (@hash{@fields} = $sth->fetchrow_array) {
125 23080         66807 my %tmp = %hash;
126 23080 100       42228 if ($set_list) {
127 22772         28314 push @{$meta_results}, \%tmp;
  22772         118148  
128             } else {
129 308         858 $self->extra_info(\%tmp);
130 308         1011 $meta_obj->set_data(\%tmp);
131 308 100       7037 if ($want_ids) {
132 298         743 my $download = download($tmp{cpanid}, $tmp{dist_file});
133 298         5008 push @{$meta_results},
134             {
135             dist_id => $tmp{dist_id},
136 298         456 download => $download
137             };
138              
139             }
140             }
141             }
142 1021 100       3894 $meta_results = undef if ($sth->rows == 0);
143 1021         2951 $sth->finish;
144 1021         10727 undef $sth;
145 1021 100       2813 return unless $meta_results;
146 1011 100       4981 $meta_obj->set_list_data($meta_results, $download) if $set_list;
147 1011 100       13704 return $want_ids ? $meta_results : 1;
148             }
149             }
150              
151             sub extra_info {
152 4052     4052 0 7008 my ($self, $results) = @_;
153 4052 100 100     13078 if ($results->{cpanid} and $results->{dist_file}) {
154 2552         7837 $results->{download} = download($results->{cpanid}, $results->{dist_file});
155             }
156 4052         7032 return;
157             }
158              
159             sub sql_statement {
160 2813     2813 1 8757 my ($self, %args) = @_;
161              
162 2813         4609 my $search = $args{search};
163 2813 100       5887 my $distinct = $search->{distinct} ? 'DISTINCT' : '';
164 2813         4234 my $table = $args{table};
165              
166 2813         4191 my $fields = $args{fields};
167 2813 50       5528 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  2813         6755  
168 2813         5505 for (@fields) {
169 22623 100       45376 $_ = $full_id->{$_} if $full_id->{$_};
170             }
171              
172 2813         10292 my $sql = qq{SELECT $distinct } . join(',', @fields);
173 2813         4305 my $where = '';
174 2813         4520 my $type = $search->{type};
175             QUERY: {
176 2813 100       3805 ($type eq 'query') and do {
  2813         5572  
177 38         83 my $value = $search->{value};
178 38 50       110 last QUERY if ($value eq '^');
179 38         71 my $name = $search->{name};
180 38         68 my $text = $search->{text};
181 38 100       224 my $use_like = ($value =~ /^\^?[A-Za-z0-9_\\\:\-]+$/) ? 1 : 0;
182 38         103 my $prepend = '%';
183 38 100 100     214 if ($use_like and $value =~ /^\^/) {
184 4         10 $prepend = '';
185 4         15 $value =~ s/^\^//;
186 4         13 $value =~ s{\\}{}g;
187             }
188             $where =
189 38 100       147 $use_like
190             ? qq{$name LIKE '$prepend$value%'}
191             : qq{$name REGEXP '(?i:$value)'};
192              
193 38 100       114 if ($name eq 'cpanid') {
194 10 100       63 $where .=
195             $use_like
196             ? qq{ OR $text LIKE '$prepend$value%'}
197             : qq{ OR $text REGEXP '(?i:$value)'};
198             }
199 38         95 last QUERY;
200             };
201 2775 100       5285 ($type eq 'id') and do {
202 1208         3128 $where = qq{ $search->{id} = $search->{value} };
203 1208         2143 last QUERY;
204             };
205 1567 50       3040 ($type eq 'name') and do {
206 1567         3557 $where = qq{ $search->{name} = '$search->{value}' };
207 1567         2556 last QUERY;
208             };
209 0         0 warn qq{Unknown query type};
210 0         0 return;
211             }
212 2813         3751 my $join;
213              
214 2813         6953 $sql .= ' FROM ' . $table;
215 2813   66     7694 my $left_join = $args{join} || $args{left_join};
216 2813 100       5643 if ($left_join) {
217 1579 50       3491 if (ref($left_join) eq 'HASH') {
218 1579         4217 foreach my $key (keys %$left_join) {
219 3052         4836 my $id = $left_join->{$key};
220 3052         8773 $sql .= " LEFT JOIN $key ON $table.$id=$key.$id ";
221             }
222             }
223             }
224              
225 2813 50       5327 if ($where) {
226 2813         5907 $sql .= ' WHERE ( ' . $where . ' )';
227 2813 50       5521 $sql .= ' AND (' . $join . ')' if $join;
228             } else {
229 0 0       0 $sql .= ' WHERE (' . $join . ')' if $join;
230             }
231              
232 2813         4125 my $order_by = '';
233 2813 50       5966 if (my $user_order_by = $args{order_by}) {
234 2813 50       5286 $order_by = $order_by ? "$order_by,$user_order_by" : $user_order_by;
235             }
236 2813 50 33     8778 if ($order_by and $where) {
237 2813         5235 $sql .= qq{ ORDER BY $order_by };
238             }
239              
240 2813 50       6348 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         12313 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.220
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