File Coverage

blib/lib/JPList/DB/Result.pm
Criterion Covered Total %
statement 6 104 5.7
branch 0 48 0.0
condition 0 19 0.0
subroutine 2 8 25.0
pod 1 1 100.0
total 9 180 5.0


line stmt bran cond sub pod time code
1             # ========================================================================== #
2             # lib/JPList/Result.pm - JPList DB Result
3             # Copyright (C) 2017 Exceleron Software, LLC
4             # ========================================================================== #
5              
6             package JPList::DB::Result;
7              
8 1     1   632 use Moose::Role;
  1         2  
  1         10  
9 1     1   5091 use SQL::Abstract;
  1         8022  
  1         896  
10              
11             # ========================================================================== #
12              
13             =head1 NAME
14              
15             JPList::DB::Result - JPList DB Result
16              
17             =head1 SYNOPSIS
18              
19             with 'JPList::DB::Result'
20              
21             =head1 DESCRIPTION
22              
23             The JPList::DB::Result module allows you get the resultset from table/view
24              
25             =head2 ATTRIBUTES
26              
27             =over 4
28              
29             =cut
30              
31             # ========================================================================== #
32              
33             has 'sql_abs' => (
34             is => 'rw',
35             isa => 'SQL::Abstract',
36             default => sub {
37             SQL::Abstract->new(quote_char => '"');
38             }
39             );
40              
41             # ========================================================================== #
42              
43             =back
44              
45             =head2 METHODS
46              
47             =over 4
48              
49             =cut
50              
51             # ========================================================================== #
52              
53             =item C<_get_resultset>
54              
55             Params : $request_data
56              
57             Returns: Resultset data from table/view based on the request params
58              
59             Desc : Resultset data from table/view based on the request params
60              
61             =cut
62              
63             sub _get_resultset
64             {
65 0     0     my $self = shift;
66 0           my $request_data = shift;
67 0   0       my $is_download = shift || 0;
68              
69 0           my $source = $self->db_table_name;
70              
71 0           my $fields;
72 0 0         if ($self->fields) {
73 0           $fields = $self->fields;
74             }
75             else {
76 0           $fields = ['*'];
77             }
78              
79 0           my $where = $self->_build_where_clause($request_data);
80              
81 0           my $order = $self->_build_sort_order($request_data);
82              
83 0           my ($sql_query, @bind_vals) = $self->sql_abs->select($source, $fields, $where);
84              
85 0 0         if ($self->group_fields) {
86 0           $sql_query .= " GROUP BY " . $self->group_fields;
87             }
88              
89 0 0         if ($order) {
90 0           $sql_query .= " $order";
91             }
92              
93 0           my $bind_vals = \@bind_vals;
94              
95 0           my $params;
96 0           my $count = 0;
97 0 0         if (!$is_download) {
98             ## Add Limit Query for jplist data
99 0           ($sql_query, $bind_vals) = $self->_build_limit_query($request_data, $sql_query, \@bind_vals);
100              
101             #Get total count for paging
102 0           $count = $self->_get_paging_count($source, $where);
103             }
104             else {
105             ## Return array of array for csv download
106 0           $params->{return_aoa} = 1;
107             }
108              
109 0           print STDERR "[jplist info] " . $sql_query . "\n";
110 0           print STDERR "[jplist info] bind_vals @bind_vals \n";
111              
112 0           $params->{sql} = $sql_query;
113 0           $params->{bind_vals} = $bind_vals;
114              
115 0           my $data = $self->select_hashref($params);
116              
117             #Return data
118 0           my $return_data = {
119             count => $count,
120             data => $data
121             };
122              
123 0           return $return_data;
124             }
125              
126             # ========================================================================== #
127              
128             =item C<_build_where_clause>
129              
130             Params : $request_data
131              
132             Returns: $where_clause
133              
134             Desc : Builds where_clause based on JPList request "filter_data" and also custom "where_fields"
135              
136             =cut
137              
138             sub _build_where_clause
139             {
140 0     0     my $self = shift;
141 0           my $request_data = shift;
142              
143 0 0         return $self->{where_clause} if ($self->{where_clause});
144              
145 0           my %where;
146              
147             #Custom Where Clause like UtilityId/AccountId/MeterId filter based on auth
148 0           foreach my $column (keys %{$self->where_fields}) {
  0            
149 0           $where{$column} = $self->where_fields->{$column};
150             }
151              
152             #Where clause applied based on filter data
153 0           foreach my $data (@{$request_data->filter_data}) {
  0            
154 0 0         if (exists($data->{'type'})) {
155 0 0         if ($data->{'type'} eq 'like') {
    0          
    0          
156 0           $where{$data->{'column'}} = {-like => '%' . $data->{'value'} . '%'};
157             }
158             elsif ($data->{'type'} eq 'between') {
159 0           $where{$data->{'column'}} = {-between => [$data->{'from_date'}, $data->{'to_date'}]};
160             }
161             elsif ($data->{'type'} eq 'in') {
162 0           $where{$data->{'column'}} = {-in => $data->{'values'}};
163             }
164             }
165             else {
166 0           $where{$data->{'column'}} = $data->{'value'};
167             }
168             }
169              
170 0           $self->{where_clause} = \%where;
171              
172 0           return $self->{where_clause};
173             }
174              
175             # ========================================================================== #
176              
177             =item C<_build_sort_order>
178              
179             Params : $request_data
180              
181             Returns: $order
182              
183             Desc : Builds order data structure based on JPList request "sort_data"
184              
185             =cut
186              
187             sub _build_sort_order
188             {
189 0     0     my $self = shift;
190 0           my $request_data = shift;
191              
192 0 0         my $sort_one = $request_data->sort_data->[0] if (ref($request_data->sort_data) eq 'ARRAY');
193              
194 0           my $order;
195 0 0 0       if ($sort_one && $sort_one->{column} ne 'default') {
196              
197 0 0         if ($self->order_index) {
198 0           my $order_index = $self->order_index->{$sort_one->{column}};
199 0           $order = qq/ORDER BY $order_index/;
200 0 0         if ($sort_one->{order} eq "desc") {
201              
202 0           $order .= ' DESC';
203              
204             }
205             }
206             else {
207 0           $order = qq/ORDER BY "$sort_one->{column}"/;
208 0 0         if ($sort_one->{order} eq "desc") {
209              
210 0           $order .= ' DESC';
211              
212             }
213             }
214              
215             }
216              
217 0           return $order;
218             }
219              
220             # ========================================================================== #
221              
222             =item C<_build_limit_query>
223              
224             Params : $request_data, $sql_query, $bind_vals
225              
226             Returns: $sql_query, $bind_vals
227              
228             Desc : Builds SQL updated with LIMIT and OFFEST based on JPList request "pagination_data"
229              
230             =cut
231              
232             sub _build_limit_query
233             {
234 0     0     my $self = shift;
235 0           my $request_data = shift;
236 0           my $sql_query = shift;
237 0           my $bind_vals = shift;
238              
239 0   0       my $number = $request_data->pagination_data->{'number'} || 10;
240 0   0       my $current_page = $request_data->pagination_data->{'currentPage'} || 0;
241              
242 0           my $limit = $number;
243 0   0       my $offset = ($limit * $current_page) || 0;
244              
245 0 0 0       if ($limit and $limit ne 'all') {
246 0           $sql_query .= " LIMIT ? OFFSET ?";
247 0           push(@$bind_vals, ($limit, $offset));
248             }
249              
250 0           return ($sql_query, $bind_vals);
251             }
252              
253             # ========================================================================== #
254              
255             =item C<_get_paging_count>
256              
257             Params : $table_source, $wheres
258              
259             Returns: total count based on filter
260              
261             Desc : total count based on filter
262              
263             =cut
264              
265             sub _get_paging_count
266             {
267 0     0     my $self = shift;
268 0           my $source = shift;
269 0           my $where = shift;
270              
271 0           my ($sql_count_query, @bind_count_vals);
272              
273 0 0         if ($self->group_fields) {
274 0           my $group_fields = $self->group_fields;
275              
276 0           ($sql_count_query, @bind_count_vals) = $self->sql_abs->select($source, $group_fields, $where);
277 0           $sql_count_query = "SELECT COUNT(*) FROM ($sql_count_query GROUP BY $group_fields) AS SQ";
278              
279             }
280             else {
281              
282 0           ($sql_count_query, @bind_count_vals) = $self->sql_abs->select($source, 'count(*)', $where);
283             }
284              
285 0           my $data = $self->select_hashref(
286             {
287             sql => $sql_count_query,
288             bind_vals => \@bind_count_vals,
289             return_aoa => 1
290             }
291             );
292              
293 0   0       my $count = $data->[0][0] || 0;
294              
295 0           return $count;
296             }
297              
298             # ========================================================================== #
299              
300             =item C<select_hashref>
301              
302             Params :
303              
304             {
305             sql => 'SQL Statement',
306             bind_vals => ARRAYREF[optional],
307             return_key => Column [optional],
308             return_aoa => 1 [optional]
309             }
310              
311             Returns: ARRAYREF/HASHREF of data
312              
313             - If return_key is undef : Returns rows as Array of Hash
314             - If return_key has a valid column: Returns rows as Hash of Hash with Column value as hash key
315             - If return_aoa is 1 : Returns rows as Array of Array
316              
317             Desc : Using SQL get hashref of data
318              
319             =cut
320              
321             sub select_hashref
322             {
323 0     0 1   my $self = shift;
324 0           my $params = shift;
325 0           my $sql = $params->{sql};
326 0 0 0       my $bind_vals = (defined($params->{'bind_vals'}) && exists($params->{'bind_vals'})) ? $params->{'bind_vals'} : [];
327              
328 0           my $dbh = $self->dbh;
329              
330 0           my $data;
331 0 0         my $sth = $dbh->prepare_cached($sql) or die("$!");
332              
333 0           for (my $i = 0; $i < scalar(@$bind_vals); $i++) {
334 0 0         $sth->bind_param($i + 1, $bind_vals->[$i]) or die("$!");
335             }
336              
337 0 0         if (defined $params->{return_key}) {
    0          
338 0 0         $data = $dbh->selectall_hashref($sth, $params->{return_key}) or die("$!");
339             }
340             elsif (defined $params->{return_aoa}) {
341 0 0         $data = $dbh->selectall_arrayref($sth) or die("$!");
342             }
343             else {
344 0 0         $data = $dbh->selectall_arrayref($sth, {Slice => {}}) or die("$!");
345             }
346            
347 0           return $data;
348             }
349              
350             # ========================================================================== #
351              
352              
353             1;
354              
355             __END__
356              
357             =back
358            
359             =head1 AUTHORS
360              
361             Sheeju Alex, <sheeju@exceleron.com>
362              
363             =head1 BUGS
364              
365             https://github.com/sheeju/JPList/issues
366              
367             =head1 SUPPORT
368              
369             You can find documentation for this module with the perldoc command.
370              
371             perldoc JPList
372              
373              
374             You can also look for information at:
375              
376             =over 4
377              
378             =item * RT: CPAN's request tracker (report bugs here)
379              
380             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=JPList>
381              
382             =item * AnnoCPAN: Annotated CPAN documentation
383              
384             L<http://annocpan.org/dist/JPList>
385              
386             =item * CPAN Ratings
387              
388             L<http://cpanratings.perl.org/d/JPList>
389              
390             =item * Search CPAN
391              
392             L<http://search.cpan.org/dist/JPList/>
393              
394             =back
395              
396             =head1 ACKNOWLEDGEMENTS
397              
398             Development time supported by Exceleron L<www.exceleron.com|http://www.exceleron.com>.
399              
400             =head1 LICENSE AND COPYRIGHT
401              
402             Copyright (C) 2017 Exceleron Software, LLC
403              
404             This program is free software; you can redistribute it and/or modify it
405             under the terms of the the Artistic License (2.0). You may obtain a
406             copy of the full license at:
407              
408             L<http://www.perlfoundation.org/artistic_license_2_0>
409              
410             Any use, modification, and distribution of the Standard or Modified
411             Versions is governed by this Artistic License. By using, modifying or
412             distributing the Package, you accept this license. Do not use, modify,
413             or distribute the Package, if you do not accept this license.
414              
415             If your Modified Version has been derived from a Modified Version made
416             by someone other than you, you are nevertheless required to ensure that
417             your Modified Version complies with the requirements of this license.
418              
419             This license does not grant you the right to use any trademark, service
420             mark, tradename, or logo of the Copyright Holder.
421              
422             This license includes the non-exclusive, worldwide, free-of-charge
423             patent license to make, have made, use, offer to sell, sell, import and
424             otherwise transfer the Package with respect to any patent claims
425             licensable by the Copyright Holder that are necessarily infringed by the
426             Package. If you institute patent litigation (including a cross-claim or
427             counterclaim) against any party alleging that the Package constitutes
428             direct or contributory patent infringement, then this Artistic License
429             to you shall terminate on the date that such litigation is filed.
430              
431             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
432             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
433             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
434             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
435             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
436             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
437             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
438             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
439              
440             =cut
441              
442             # vim: ts=4
443             # vim600: fdm=marker fdl=0 fdc=3