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