From: Andy Grundman Date: Fri, 26 Aug 2005 19:27:02 +0000 (+0000) Subject: Added pager support, same syntax as Sweet. Also fixed a few issues with ResultSet... X-Git-Tag: v0.03001~25 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=59f8e58434e28bd6005d9dfcca75a0efbb4f49e1;hp=0675cd04337cafdc5a8ce19e707e3b2ce2508087;p=dbsrgits%2FDBIx-Class.git Added pager support, same syntax as Sweet. Also fixed a few issues with ResultSet::count. Table::count still does 2 SQL queries, we need to figure out how to fix that --- diff --git a/Build.PL b/Build.PL index 0853b8f..fd130ca 100644 --- a/Build.PL +++ b/Build.PL @@ -6,6 +6,7 @@ my %arguments = ( license => 'perl', module_name => 'DBIx::Class', requires => { + 'Data::Page' => 0, 'DBI' => 0, 'UNIVERSAL::require' => 0, 'NEXT' => 0, diff --git a/lib/DBIx/Class/Core.pm b/lib/DBIx/Class/Core.pm index 5dc4096..b1d95fa 100644 --- a/lib/DBIx/Class/Core.pm +++ b/lib/DBIx/Class/Core.pm @@ -9,6 +9,7 @@ use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/ InflateColumn Relationship + Pager PK Row Table diff --git a/lib/DBIx/Class/Pager.pm b/lib/DBIx/Class/Pager.pm new file mode 100644 index 0000000..1d715da --- /dev/null +++ b/lib/DBIx/Class/Pager.pm @@ -0,0 +1,65 @@ +package DBIx::Class::Pager; + +use strict; +use warnings; + +use NEXT; +use Data::Page; + +=head1 NAME + +DBIx::Class::Pager - Pagination of resultsets + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +This class lets you page through a resultset. + +=head1 METHODS + +=over 4 + +=item page + +=item pager + +=cut + +*pager = \&page; + +sub page { + my $self = shift; + my ($criteria, $attr) = @_; + + my $rows = $attr->{rows} || 10; + my $current = $attr->{page} || 1; + + # count must not use LIMIT, so strip out rows/offset + delete $attr->{$_} for qw/rows offset/; + + my $total = $self->count( $criteria, $attr ); + my $page = Data::Page->new( $total, $rows, $current ); + + $attr->{rows} = $page->entries_per_page; + $attr->{offset} = $page->skipped; + + my $iterator = $self->search( $criteria, $attr ); + + return ( $page, $iterator ); +} + +1; + +=back + +=head1 AUTHORS + +Andy Grundman + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. + +=cut + diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 644ff76..936bfdb 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -42,15 +42,19 @@ sub next { sub count { my ($self) = @_; - return $self->{attrs}{rows} if $self->{attrs}{rows}; - # This is a hack, and will break on the last page of a paged set. - # Once we have limit support in Storage, kill it. - my $db_class = $self->{class}; + + # offset breaks COUNT(*), so remove it + my $attrs = { %{ $self->{attrs} } }; + delete $attrs->{offset}; + my @cols = 'COUNT(*)'; my ($c) = $db_class->storage->select_single($db_class->_table_name, \@cols, - $self->{cond}, $self->{attrs}); - return $c; # ($cursor->next)[0]; + $self->{cond}, $attrs); + return 0 unless $c; + return ( $attrs->{rows} && $attrs->{rows} < $c ) + ? $attrs->{rows} + : $c; } sub all { diff --git a/t/07pager.t b/t/07pager.t new file mode 100644 index 0000000..38a290a --- /dev/null +++ b/t/07pager.t @@ -0,0 +1,72 @@ +use Test::More; + +plan tests => 8; + +use lib qw(t/lib); + +use_ok('DBICTest'); + +# first page +my ( $pager, $it ) = DBICTest::CD->page( + {}, + { order_by => 'title', + rows => 3, + page => 1 } +); + +is( $pager->entries_on_this_page, 3, "entries_on_this_page ok" ); + +is( $pager->next_page, 2, "next_page ok" ); + +is( $it->next->title, "Caterwaulin' Blues", "iterator->next ok" ); + +$it->next; +$it->next; + +is( $it->next, undef, "next past end of page ok" ); + +# second page +( $pager, $it ) = DBICTest::CD->page( + {}, + { order_by => 'title', + rows => 3, + page => 2 } +); + +is( $pager->entries_on_this_page, 2, "entries on second page ok" ); + +is( $it->next->title, "Generic Manufactured Singles", "second page first title ok" ); + +# XXX: Should we support disable_sql_paging? +#( $pager, $it ) = DBICTest::CD->page( +# {}, +# { rows => 2, +# page => 2, +# disable_sql_paging => 1 } ); +# +#cmp_ok( $pager->total_entries, '==', 5, "disable_sql_paging total_entries ok" ); +# +#cmp_ok( $pager->previous_page, '==', 1, "disable_sql_paging previous_page ok" ); +# +#is( $it->next->title, "Caterwaulin' Blues", "disable_sql_paging iterator->next ok" ); +# +#$it->next; +# +#is( $it->next, undef, "disable_sql_paging next past end of page ok" ); + +# based on a failing criteria submitted by waswas +# requires SQL::Abstract >= 1.20 +( $pager, $it ) = DBICTest::CD->page( + { title => [ + -and => + { + -like => '%bees' + }, + { + -not_like => 'Forkful%' + } + ] + }, + { rows => 5 } +); +is( $it->count, 1, "complex abstract count ok" );