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 82 2020-05-30 06:14:27Z stro $
2              
3             package CPAN::SQLite::DBI::Search;
4              
5 5     5   42 use strict;
  5         22  
  5         154  
6 5     5   40 use warnings;
  5         9  
  5         497  
7              
8             BEGIN {
9 5     5   31 our $VERSION = '0.218';
10 5         12 $CPAN::SQLite::DBI::Search::info::VERSION = $VERSION;
11 5         9 $CPAN::SQLite::DBI::Search::mods::VERSION = $VERSION;
12 5         45 $CPAN::SQLite::DBI::Search::dists::VERSION = $VERSION;
13 5         153 $CPAN::SQLite::DBI::Search::auths::VERSION = $VERSION;
14             }
15              
16 5     5   38 use parent 'CPAN::SQLite::DBI';
  5         11  
  5         59  
17 5     5   306 use CPAN::SQLite::DBI qw($tables $dbh);
  5         17  
  5         644  
18 5     5   44 use CPAN::SQLite::Util qw($full_id);
  5         10  
  5         419  
19              
20             package CPAN::SQLite::DBI::Search::info;
21 5     5   34 use parent 'CPAN::SQLite::DBI::Search';
  5         14  
  5         21  
22 5     5   321 use CPAN::SQLite::DBI qw($dbh);
  5         11  
  5         476  
23              
24             package CPAN::SQLite::DBI::Search::mods;
25 5     5   35 use parent 'CPAN::SQLite::DBI::Search';
  5         9  
  5         30  
26 5     5   348 use CPAN::SQLite::DBI qw($dbh);
  5         11  
  5         501  
27              
28             package CPAN::SQLite::DBI::Search::dists;
29 5     5   52 use parent 'CPAN::SQLite::DBI::Search';
  5         18  
  5         22  
30 5     5   325 use CPAN::SQLite::DBI qw($dbh);
  5         13  
  5         445  
31              
32             package CPAN::SQLite::DBI::Search::auths;
33 5     5   35 use parent 'CPAN::SQLite::DBI::Search';
  5         10  
  5         29  
34 5     5   359 use CPAN::SQLite::DBI qw($dbh);
  5         9  
  5         407  
35              
36             package CPAN::SQLite::DBI::Search;
37 5     5   33 use parent 'CPAN::SQLite::DBI';
  5         12  
  5         42  
38 5     5   465 use CPAN::SQLite::DBI qw($tables $dbh);
  5         11  
  5         499  
39 5     5   37 use CPAN::SQLite::Util qw($full_id download);
  5         10  
  5         8943  
40              
41             sub fetch {
42 871     871 1 2988 my ($self, %args) = @_;
43 871         1434 my $fields = $args{fields};
44 871         1204 my $search = $args{search};
45 871 50       2033 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  871         2446  
46 871 50       2776 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       5684 my $sth = $dbh->prepare($sql) or do {
51 0         0 $self->db_error();
52 0         0 return;
53             };
54 871 50       185194 $sth->execute() or do {
55 0         0 $self->db_error($sth);
56 0         0 return;
57             };
58              
59 871 100       10901 if (not $search->{wantarray}) {
60 646         1171 my (%results, $results);
61 646         11962 @results{@fields} = $sth->fetchrow_array;
62 646 100       3239 $results = ($sth->rows == 0) ? undef : \%results;
63 646         2347 $sth->finish;
64 646         8525 undef $sth;
65 646 100       2846 $self->extra_info($results) if $results;
66 646         4185 return $results;
67             } else {
68 225         374 my (%hash, $results);
69 225         2213 while (@hash{@fields} = $sth->fetchrow_array) {
70 2191         11351 my %tmp = %hash;
71 2191         6238 $self->extra_info(\%tmp);
72 2191         3106 push @{$results}, \%tmp;
  2191         14777  
73             }
74 225 100       828 $results = undef if ($sth->rows == 0);
75 225         658 $sth->finish;
76 225         2178 undef $sth;
77 225         1347 return $results;
78             }
79             }
80              
81             sub fetch_and_set {
82 1942     1942 0 7528 my ($self, %args) = @_;
83 1942         3280 my $fields = $args{fields};
84 1942         3027 my $search = $args{search};
85 1942         2805 my $meta_obj = $args{meta_obj};
86 1942 50 33     11445 die "Please supply a CPAN::SQLite::Meta::* object"
87             unless ($meta_obj and ref($meta_obj) =~ /^CPAN::SQLite::META/);
88 1942 50       4993 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  1942         5494  
89 1942 50       6458 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       12912 my $sth = $dbh->prepare($sql) or do {
94 0         0 $self->db_error();
95 0         0 return;
96             };
97 1942 50       386672 $sth->execute() or do {
98 0         0 $self->db_error($sth);
99 0         0 return;
100             };
101              
102 1942         12606 my $want_ids = $args{want_ids};
103 1942         3175 my $set_list = $args{set_list};
104 1942         3305 my $download = $args{download};
105 1942 100       5028 if (not $search->{wantarray}) {
106 921         1722 my (%results, %meta_results, $results);
107 921         16636 @results{@fields} = $sth->fetchrow_array;
108 921 100       4119 $results = ($sth->rows == 0) ? undef : \%results;
109 921         3443 $sth->finish;
110 921         12561 undef $sth;
111 921 100       2688 return unless $results;
112 913         2531 $self->extra_info($results);
113 913         3239 $meta_obj->set_data($results);
114              
115 913 100       22718 if ($want_ids) {
116 907         1985 $meta_results{dist_id} = $results{dist_id};
117 907         2595 $meta_results{download} = download($results{cpanid}, $results{dist_file});
118 907         7495 return \%meta_results;
119             } else {
120 6         42 return 1;
121             }
122             } else {
123 1021         1764 my (%hash, $meta_results);
124 1021         9375 while (@hash{@fields} = $sth->fetchrow_array) {
125 23080         63506 my %tmp = %hash;
126 23080 100       41255 if ($set_list) {
127 22772         28079 push @{$meta_results}, \%tmp;
  22772         111669  
128             } else {
129 308         880 $self->extra_info(\%tmp);
130 308         1006 $meta_obj->set_data(\%tmp);
131 308 100       7332 if ($want_ids) {
132 298         789 my $download = download($tmp{cpanid}, $tmp{dist_file});
133 298         4612 push @{$meta_results},
134             {
135             dist_id => $tmp{dist_id},
136 298         489 download => $download
137             };
138              
139             }
140             }
141             }
142 1021 100       4027 $meta_results = undef if ($sth->rows == 0);
143 1021         2876 $sth->finish;
144 1021         10394 undef $sth;
145 1021 100       2706 return unless $meta_results;
146 1011 100       4516 $meta_obj->set_list_data($meta_results, $download) if $set_list;
147 1011 100       13781 return $want_ids ? $meta_results : 1;
148             }
149             }
150              
151             sub extra_info {
152 4052     4052 0 7122 my ($self, $results) = @_;
153 4052 100 100     12880 if ($results->{cpanid} and $results->{dist_file}) {
154 2552         8055 $results->{download} = download($results->{cpanid}, $results->{dist_file});
155             }
156 4052         6929 return;
157             }
158              
159             sub sql_statement {
160 2813     2813 1 9016 my ($self, %args) = @_;
161              
162 2813         4501 my $search = $args{search};
163 2813 100       5916 my $distinct = $search->{distinct} ? 'DISTINCT' : '';
164 2813         4156 my $table = $args{table};
165              
166 2813         3863 my $fields = $args{fields};
167 2813 50       5342 my @fields = ref($fields) eq 'ARRAY' ? @{$fields} : ($fields);
  2813         6706  
168 2813         5600 for (@fields) {
169 22623 100       43731 $_ = $full_id->{$_} if $full_id->{$_};
170             }
171              
172 2813         10540 my $sql = qq{SELECT $distinct } . join(',', @fields);
173 2813         4835 my $where = '';
174 2813         4501 my $type = $search->{type};
175             QUERY: {
176 2813 100       3752 ($type eq 'query') and do {
  2813         5846  
177 38         76 my $value = $search->{value};
178 38 50       85 last QUERY if ($value eq '^');
179 38         68 my $name = $search->{name};
180 38         93 my $text = $search->{text};
181 38 100       221 my $use_like = ($value =~ /^\^?[A-Za-z0-9_\\\:\-]+$/) ? 1 : 0;
182 38         79 my $prepend = '%';
183 38 100 100     193 if ($use_like and $value =~ /^\^/) {
184 4         12 $prepend = '';
185 4         17 $value =~ s/^\^//;
186 4         14 $value =~ s{\\}{}g;
187             }
188             $where =
189 38 100       152 $use_like
190             ? qq{$name LIKE '$prepend$value%'}
191             : qq{$name REGEXP '(?i:$value)'};
192              
193 38 100       95 if ($name eq 'cpanid') {
194 10 100       58 $where .=
195             $use_like
196             ? qq{ OR $text LIKE '$prepend$value%'}
197             : qq{ OR $text REGEXP '(?i:$value)'};
198             }
199 38         81 last QUERY;
200             };
201 2775 100       5211 ($type eq 'id') and do {
202 1208         3170 $where = qq{ $search->{id} = $search->{value} };
203 1208         2190 last QUERY;
204             };
205 1567 50       3164 ($type eq 'name') and do {
206 1567         3577 $where = qq{ $search->{name} = '$search->{value}' };
207 1567         2598 last QUERY;
208             };
209 0         0 warn qq{Unknown query type};
210 0         0 return;
211             }
212 2813         3755 my $join;
213              
214 2813         7225 $sql .= ' FROM ' . $table;
215 2813   66     7427 my $left_join = $args{join} || $args{left_join};
216 2813 100       6122 if ($left_join) {
217 1579 50       3317 if (ref($left_join) eq 'HASH') {
218 1579         4193 foreach my $key (keys %$left_join) {
219 3052         4833 my $id = $left_join->{$key};
220 3052         8734 $sql .= " LEFT JOIN $key ON $table.$id=$key.$id ";
221             }
222             }
223             }
224              
225 2813 50       5512 if ($where) {
226 2813         6305 $sql .= ' WHERE ( ' . $where . ' )';
227 2813 50       5476 $sql .= ' AND (' . $join . ')' if $join;
228             } else {
229 0 0       0 $sql .= ' WHERE (' . $join . ')' if $join;
230             }
231              
232 2813         4548 my $order_by = '';
233 2813 50       5823 if (my $user_order_by = $args{order_by}) {
234 2813 50       5237 $order_by = $order_by ? "$order_by,$user_order_by" : $user_order_by;
235             }
236 2813 50 33     9024 if ($order_by and $where) {
237 2813         5297 $sql .= qq{ ORDER BY $order_by };
238             }
239              
240 2813 50       5649 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         11971 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.218
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