File Coverage

blib/lib/DBIx/Foo/SearchQuery.pm
Criterion Covered Total %
statement 6 143 4.2
branch 0 62 0.0
condition 0 41 0.0
subroutine 2 22 9.0
pod 0 20 0.0
total 8 288 2.7


line stmt bran cond sub pod time code
1             package DBIx::Foo::SearchQuery;
2              
3 4     4   27 use strict;
  4         9  
  4         133  
4              
5 4     4   4872 use Storable;
  4         26134  
  4         8150  
6              
7             sub new {
8              
9 0     0 0   my $class = $_[0];
10 0           my $query = $_[1];
11 0   0       my $page = $_[2] || 1;
12 0   0       my $pagesize = $_[3] || 20;
13 0   0       my $relation = $_[4] || ' and ';
14              
15 0           my $self = {
16             query => $query,
17             page => $page,
18             pagesize => $pagesize,
19             relation => $relation,
20             debug => 0
21             };
22              
23 0           bless $self, $class;
24              
25 0           return $self;
26             }
27              
28             ####################################################
29             # Properties
30             #
31              
32             sub IsEmptySearch {
33              
34 0     0 0   my $self = $_[0];
35              
36 0 0         return 0 if scalar keys %{$self->{filter_fields}} > 0;
  0            
37 0 0         return 0 if scalar keys %{$self->{search_fields}} > 0;
  0            
38 0 0         return 0 if scalar keys %{$self->{match_fields}} > 0;
  0            
39 0 0         return 0 unless $self->{sql_fields};
40              
41 0           return 1;
42             }
43              
44             sub CurrentPage {
45              
46 0     0 0   my $self = $_[0];
47              
48 0           return $self->{page};
49              
50             }
51              
52             sub PageSize {
53              
54 0     0 0   my $self = $_[0];
55              
56 0           return $self->{pagesize};
57              
58             }
59              
60              
61             sub RowcountQuery {
62              
63 0     0 0   my $self = $_[0];
64              
65 0           my ($where, @args) = $self->WhereClause();
66              
67 0           my $query = $self->{query} . $where;
68              
69 0           $query = "select count(*) " . substr($query, index($query, "from"));
70              
71 0           return $query, @args;
72             }
73              
74             sub DoSearch {
75              
76 0     0 0   my ($self, $dbh) = @_;
77              
78 0           my ($query, @args) = $self->Query();
79              
80 0           return $dbh->selectall_arrayref($query, { Slice => {} }, @args);
81             }
82              
83             sub DoSearchAsArray {
84              
85 0     0 0   my ($self, $dbh) = @_;
86              
87 0           my ($query, @args) = $self->Query();
88              
89 0           return $dbh->selectall_arrayref($query, { Slice => () }, @args);
90             }
91              
92             sub DoSearchAsColArray {
93              
94 0     0 0   my ($self, $dbh) = @_;
95              
96 0           my ($query, @args) = $self->Query();
97              
98 0           return $dbh->selectcol_arrayref($query, @args);
99             }
100              
101             sub GetRowcount {
102              
103 0     0 0   my ($self, $dbh) = @_;
104              
105 0           my ($query, @args) = $self->RowcountQuery();
106              
107 0           return $dbh->selectrow_array($query, {}, @args);
108             }
109              
110             sub Query {
111              
112 0     0 0   my $self = $_[0];
113              
114 0           my $logger = Log::Log4perl->get_logger('db.searchquery.query');
115              
116 0           my $caller = ( caller(2) )[3];
117              
118 0           my ($where, @args) = $self->WhereClause();
119              
120 0           my $query = $self->{query} . $where . $self->SortOrder . $self->Limit;
121              
122 0           $logger->debug("$query (" . join(", ", @args) . ") called by $caller");
123              
124 0           return $query, @args;
125             }
126              
127             sub WhereClause {
128              
129 0     0 0   my $self = $_[0];
130              
131 0           my $search = "";
132 0           my $filter = "";
133 0           my $sql_fields = "";
134 0           my $match = "";
135 0           my $predicate = "";
136              
137 0           my @args;
138              
139 0           for my $field (keys %{$self->{search_fields}}) {
  0            
140              
141 0 0         $search .= $self->{relation} if $search;
142 0           $search .= "$field like ?";
143 0           push @args, '%' . $self->{search_fields}->{$field} . '%';
144             }
145              
146 0 0         $search = "($search)" if scalar keys %{$self->{search_fields}} > 1;
  0            
147              
148 0           for my $field (keys %{$self->{filter_fields}}) {
  0            
149              
150             # TODO May need to handle various data types here e.g. numeric, date
151             # but for now mysql will accept these as strings
152              
153 0 0         $filter .= " and " if $filter;
154              
155 0 0         if (ref($self->{filter_fields}->{$field}) eq 'ARRAY') {
156              
157 0           my @placeholders;
158              
159 0           foreach my $value (@{$self->{filter_fields}->{$field}}) {
  0            
160              
161 0           push @placeholders, '?';
162 0           push @args, $value;
163             }
164              
165 0           $filter .= "$field in (" . (join ',', @placeholders) . ')';
166             }
167             else {
168 0           $filter .= "$field = ?";
169 0           push @args, $self->{filter_fields}->{$field};
170             }
171             }
172              
173 0           for my $field (keys %{$self->{match_fields}}) {
  0            
174              
175 0 0         $match .= " and " if $match;
176              
177 0           $match .= "match ($field) against (?)";
178 0           push @args, $self->{match_fields}->{$field};
179             }
180              
181 0           $predicate = $self->{predicate_fields}->{predicate};
182              
183 0 0         if ($self->{sql_fields}) {
184 0           for my $field (@{$self->{sql_fields}}) {
  0            
185              
186 0 0         $sql_fields .= " and " if $sql_fields;
187 0           $sql_fields .= $field;
188             }
189             }
190              
191             # Match ... against ...
192              
193 0           my $where = '';
194              
195 0 0 0       $where = " where " if $filter || $search || $sql_fields || $match || $predicate;
      0        
      0        
      0        
196 0 0         $where .= "$search " if $search;
197              
198 0 0 0       $where .= "and " if $search && $filter;
199 0 0         $where .= "$filter " if $filter;
200              
201 0 0 0       $where .= "and " if ($filter || $search) && $sql_fields;
      0        
202 0 0         $where .= "$sql_fields " if $sql_fields;
203              
204 0 0 0       $where .= "and " if ($filter || $search || $sql_fields) && $match;
      0        
205 0 0         $where .= "$match " if $match;
206              
207 0 0 0       $where .= "and " if ($filter || $search || $sql_fields ||$match) && $predicate;
      0        
208 0 0         $where .= "$predicate " if $predicate;
209              
210 0           return $where, @args;
211             }
212              
213             sub SortOrder {
214              
215 0     0 0   my $self = $_[0];
216              
217 0           my $orderby;
218              
219             # TODO Add logic to build sort order clause from array
220 0 0         if ($self->{sort}) {
221              
222 0           foreach my $sortfield (@{$self->{sort}}) {
  0            
223              
224 0 0         $orderby .= ", " if $orderby;
225              
226 0           $orderby .= $sortfield;
227             }
228             }
229              
230 0 0         $orderby = " order by $orderby" if $orderby;
231              
232 0           return $orderby;
233             }
234              
235             sub Limit {
236              
237 0     0 0   my $self = $_[0];
238              
239             # TODO Add logic to build limit clause from object properties, and handle pages
240              
241 0           my $start = $self->{pagesize} * ($self->{page} - 1);
242 0           my $rows = $self->{pagesize};
243              
244 0           return " limit $start, $rows";
245             }
246              
247              
248             ####################################################
249             # Methods
250             #
251              
252             sub addSearch
253             {
254 0     0 0   my ($self, $field, $value) = @_;
255              
256 0 0         if ($value) {
257 0           $self->{search_fields}->{$field} = $value;
258             }
259             }
260              
261              
262             sub addFilter
263             {
264 0     0 0   my ($self, $field, $value) = @_;
265              
266 0 0         if ($value) {
267 0           $self->{filter_fields}->{$field} = $value;
268             }
269             }
270              
271             sub addMatch
272             {
273 0     0 0   my ($self, $field, $value) = @_;
274              
275 0 0         if ($value) {
276 0           $self->{match_fields}->{$field} = $value;
277             }
278             }
279              
280             sub addPredicate {
281              
282 0     0 0   my $self = $_[0];
283 0           my $value = $_[1];
284              
285 0           $self->{predicate_fields}->{predicate} = $value;
286              
287             }
288              
289             sub addSql
290             {
291             # Allows addition of free sql as an extra field
292             # intended use e.g. $query->addSql("OtherID in (select OtherID from others where OtherName like '%" . $self->param('other') . "%')" ) if $self->param('other');
293              
294 0     0 0   my ($self, $value) = @_;
295              
296 0 0         $self->{sql_fields} = [] unless $self->{sql_fields};
297              
298 0 0         if ($value) {
299 0           push @{$self->{sql_fields}}, $value;
  0            
300             }
301             }
302              
303             sub addSort {
304              
305 0     0 0   my $self = shift;
306 0           my $field = shift;
307 0   0       my $order = shift || "ASC";
308              
309 0 0         if (ref($field) eq 'HASH') {
310              
311 0           my $data = \%{$field};
  0            
312              
313 0           $field = $data->{sortfield};
314 0           $order = $data->{sortorder};
315             }
316              
317 0 0         if ($field) {
318 0           push(@{$self->{sort}}, "$field $order");
  0            
319             }
320             }
321              
322             sub freeze {
323              
324 0     0 0   my $self = shift;
325              
326 0           return Storable::freeze($self);
327             }
328              
329              
330              
331             1;
332