File Coverage

blib/lib/Teng/Plugin/SearchBySQLAbstractMore/Pager/Count.pm
Criterion Covered Total %
statement 53 54 98.1
branch 8 10 80.0
condition 2 3 66.6
subroutine 10 10 100.0
pod 1 2 50.0
total 74 79 93.6


line stmt bran cond sub pod time code
1             package Teng::Plugin::SearchBySQLAbstractMore::Pager::Count;
2              
3 2     2   1735 use strict;
  2         5  
  2         59  
4 2     2   18 use warnings;
  2         4  
  2         53  
5 2     2   10 use utf8;
  2         5  
  2         9  
6 2     2   55 use Carp ();
  2         4  
  2         39  
7 2     2   10 use Teng::Iterator;
  2         4  
  2         46  
8 2     2   445 use Data::Page;
  2         5334  
  2         16  
9 2     2   540 use Teng::Plugin::SearchBySQLAbstractMore ();
  2         7  
  2         2013  
10              
11             our @EXPORT = qw/search_by_sql_abstract_more_with_pager/;
12              
13             sub init {
14 2     2 0 205 $_[1]->Teng::Plugin::SearchBySQLAbstractMore::_init();
15             }
16              
17             # work around
18             push @EXPORT, qw/sql_abstract_more_instance/;
19             *sql_abstract_more_instance = \&Teng::Plugin::SearchBySQLAbstractMore::sql_abstract_more_instance;
20              
21             sub search_by_sql_abstract_more_with_pager {
22 6     6 1 60380 my ($self, $table_name, $where, $_opt) = @_;
23              
24 6         24 ($table_name, my($args, $rows, $page)) = Teng::Plugin::SearchBySQLAbstractMore::_arrange_args($table_name, $where, $_opt);
25              
26 6 50       24 my $table = $self->schema->get_table($table_name) or Carp::croak("No such table $table_name");
27 6         82 my ($sql, $binds, $count_sql, $count_binds) = _create_sqls($self, $args);
28 6         16 my ($total_entries, $itr);
29 6         11 do {
30 6         32 my $txn_scope = $self->txn_scope;
31 6         667 my $count_sth = $self->execute($count_sql, \@$count_binds);
32 6         1086 my $sth = $self->execute($sql, \@$binds);
33 6         1427 ($total_entries) = $count_sth->fetchrow_array();
34 6         27 $itr = Teng::Iterator->new(
35             teng => $self,
36             sth => $sth,
37             sql => $sql,
38             row_class => $self->schema->get_row_class($table_name),
39             table_name => $table_name,
40             suppress_object_creation => $self->suppress_row_objects,
41             );
42 6         197 $txn_scope->commit;
43             };
44 6         360 my $pager = Data::Page->new();
45 6         368 $pager->entries_per_page($rows);
46 6         81 $pager->current_page($page);
47 6         67 $pager->total_entries($total_entries);
48 6         72 return ([$itr->all], $pager);
49             }
50              
51             sub _create_sqls {
52 11     11   30348 my ($self, $args) = @_;
53              
54 11         40 my $sql_abstract_more = $self->sql_abstract_more_instance;
55 11         747 my $hint_columns = delete $args->{-hint_columns};
56 11         58 my ($sql, @binds) = $sql_abstract_more->select(%$args);
57              
58 11         11543 delete @{$args}{qw/-offset -limit -order_by/};
  11         43  
59 11 50 66     54 if ($args->{-group_by} and $self->dbh->{Driver}->{Name} eq 'mysql') {
60 0         0 $args->{-order_by} = 'NULL';
61             }
62              
63 11 100       322 if (not $args->{-group_by}) {
    100          
64 5         15 $args->{-columns} = ['count(*)'];
65             } elsif ($hint_columns) {
66 2         5 $args->{-columns} = $hint_columns;
67             }
68 11         44 my ($count_sql, @count_binds) = $sql_abstract_more->select(%$args);
69 11 100       8817 if ($args->{-group_by}) {
70 6         21 $count_sql = "SELECT COUNT(*) AS cnt FROM ($count_sql) AS total_count";
71             }
72 11         66 return ($sql, \@binds, $count_sql, \@count_binds);
73             }
74              
75             =pod
76              
77             =head1 NAME
78              
79             Teng::Plugin::SearchBySQLAbstractMore::Pager::Count - pager plugin using SQL::AbstractMore. count total entry by count(*)
80              
81             =head1 SYNOPSIS
82              
83             see Teng::Plugin::SearchBySQLAbstractMore
84              
85             =head1 CAUTION
86              
87             This solution is bad when you have many records. You re-consider the implementation where you want to use this module.
88             If you are using MySQL, I recommend to use Pager::CountOrMySQLFoundRows or Pager::MySQLFoundRows.
89              
90             =head1 METHODS
91              
92             =head2 search_by_sql_abstract_more_with_pager
93              
94             C<search_by_sql_abstract_more> with paging feature.
95             additional parameter can be taken, C<page>, C<rows> and C<hint_columns>.
96              
97             =head3 hint_columns
98              
99             If you pass C<hint_columns>, or C<-hint_columns> as option and select using "GROUP BY", it uses these values as select columns for calculating total count.
100              
101             For example:
102              
103             my ($rows, $pager) = $teng->search_by_sql_abstrat_more_with_pager
104             ('clicks',
105             {},
106             {-columns => [qw/user_id count(*) date(clicked_datetime)/],
107             -group_by => [qw/user_id date(clicked_datetime)/],
108             -rows => 20,
109             -page => 1,
110             }
111             );
112              
113             It execute the following 2 SQLs.
114              
115             SELECT COUNT(*) AS cnt FROM (SELECT user_id,DATE(clicked_datetime),COUNT(*) FROM clicks GROUP BY user_id, date(clicked_datetime)) AS total_count;
116             SELECT user_id, date(clicked_datetime), COUNT(*) FROM clicks GROUP BY user_id, date(clicked_datetime) LIMIT 20 OFFSET 0;
117              
118             If you pass -hint_columns option.
119              
120             my ($rows, $pager) = $teng->search_by_sql_abstrat_more_with_pager
121             ('clicks',
122             {},
123             {-columns => [qw/user_id count(*) date(clicked_datetime)/],
124             -group_by => [qw/user_id date(clicked_datetime)/],
125             -hint_columns => [qw/user_id/],
126             -rows => 20,
127             -page => 1,
128             }
129             );
130              
131             It execute the following 2 SQLs.
132              
133             SELECT COUNT(*) AS cnt FROM (SELECT user_id FROM clicks GROUP BY user_id, date(clicked_datetime)) AS total_count;
134             SELECT user_id,date(clicked_datetime) FROM clicks GROUP BY user_id, date(clicked_datetime) LIMIT 20 OFFSET 0;
135              
136             =head1 AUTHOR
137              
138             Ktat, C<< <ktat at cpan.org> >>
139              
140             =head1 BUGS
141              
142             Please report any bugs or feature requests to C<bug-teng-plugin-searchbysqlabstractmore at rt.cpan.org>, or through
143             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Teng-Plugin-SearchBySQLAbstractMore>. I will be notified, and then you'll
144             automatically be notified of progress on your bug as I make changes.
145              
146             =head1 SUPPORT
147              
148             You can find documentation for this module with the perldoc command.
149              
150             perldoc Teng::Plugin::SearchBySQLAbstractMore
151              
152             You can also look for information at:
153              
154             =over 4
155              
156             =item * RT: CPAN's request tracker
157              
158             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Teng-Plugin-SearchBySQLAbstractMore>
159              
160             =item * AnnoCPAN: Annotated CPAN documentation
161              
162             L<http://annocpan.org/dist/Teng-Plugin-SearchBySQLAbstractMore>
163              
164             =item * CPAN Ratings
165              
166             L<http://cpanratings.perl.org/d/Teng-Plugin-SearchBySQLAbstractMore>
167              
168             =item * Search CPAN
169              
170             L<http://search.cpan.org/dist/Teng-Plugin-SearchBySQLAbstractMore/>
171              
172             =back
173              
174              
175             =head1 ACKNOWLEDGEMENTS
176              
177              
178             =head1 LICENSE AND COPYRIGHT
179              
180             Copyright 2012 Ktat.
181              
182             This program is free software; you can redistribute it and/or modify it
183             under the terms of either: the GNU General Public License as published
184             by the Free Software Foundation; or the Artistic License.
185              
186             See http://dev.perl.org/licenses/ for more information.
187              
188              
189             =cut
190              
191             1; # End of Teng::Plugin::SearchBySQLAbstractMore::Pager::Count