From: Andy Grundman Date: Sun, 28 Aug 2005 02:19:12 +0000 (+0000) Subject: Refactored pagination into search method, Sweet syntax is now in Compat X-Git-Tag: v0.03001~23 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=2a21de92912f460837806a8f1d0a6f8b892609da;p=dbsrgits%2FDBIx-Class.git Refactored pagination into search method, Sweet syntax is now in Compat --- diff --git a/MANIFEST b/MANIFEST index 33213a9..be95530 100644 --- a/MANIFEST +++ b/MANIFEST @@ -19,6 +19,7 @@ lib/DBIx/Class/CDBICompat/LazyLoading.pm lib/DBIx/Class/CDBICompat/LiveObjectIndex.pm lib/DBIx/Class/CDBICompat/MightHave.pm lib/DBIx/Class/CDBICompat/ObjIndexStubs.pm +lib/DBIx/Class/CDBICompat/Pager.pm lib/DBIx/Class/CDBICompat/ReadOnly.pm lib/DBIx/Class/CDBICompat/Retrieve.pm lib/DBIx/Class/CDBICompat/Stringify.pm @@ -58,6 +59,7 @@ t/03podcoverage.t t/04db.t t/05multipk.t t/06relationship.t +t/07pager.t t/08inflate.t t/08inflate_has_a.t t/09update.t @@ -83,6 +85,7 @@ t/cdbi-t/16-reserved.t t/cdbi-t/18-has_a.t t/cdbi-t/19-set_sql.t t/cdbi-t/21-iterator.t +t/cdbi-t/30-pager.t t/cdbi-t/98-failure.t t/lib/DBICTest.pm t/lib/DBICTest/Schema.pm diff --git a/lib/DBIx/Class/CDBICompat.pm b/lib/DBIx/Class/CDBICompat.pm index 08bc7c9..c221a61 100644 --- a/lib/DBIx/Class/CDBICompat.pm +++ b/lib/DBIx/Class/CDBICompat.pm @@ -23,6 +23,7 @@ __PACKAGE__->load_own_components(qw/ AutoUpdate TempColumns Retrieve + Pager ColumnGroups ImaDBI/); diff --git a/lib/DBIx/Class/CDBICompat/Pager.pm b/lib/DBIx/Class/CDBICompat/Pager.pm new file mode 100644 index 0000000..cd01047 --- /dev/null +++ b/lib/DBIx/Class/CDBICompat/Pager.pm @@ -0,0 +1,16 @@ +package DBIx::Class::CDBICompat::Pager; + +use strict; +use warnings FATAL => 'all'; + +*pager = \&page; + +sub page { + my $class = shift; + + my $it = $class->search(@_); + my $pager = $class->_page_object; + return ( $pager, $it ); +} + +1; diff --git a/lib/DBIx/Class/Core.pm b/lib/DBIx/Class/Core.pm index b1d95fa..5dc4096 100644 --- a/lib/DBIx/Class/Core.pm +++ b/lib/DBIx/Class/Core.pm @@ -9,7 +9,6 @@ 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 deleted file mode 100644 index 1d715da..0000000 --- a/lib/DBIx/Class/Pager.pm +++ /dev/null @@ -1,65 +0,0 @@ -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 3f8403d..72ea52f 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -49,9 +49,9 @@ sub count { my ($self) = @_; my $db_class = $self->{class}; - # offset breaks COUNT(*), so remove it + # offset and order by are not needed to count my $attrs = { %{ $self->{attrs} } }; - delete $attrs->{offset}; + delete $attrs->{$_} for qw/offset order_by/; my @cols = 'COUNT(*)'; my ($c) = $db_class->storage->select_single($db_class->_table_name, \@cols, diff --git a/lib/DBIx/Class/Table.pm b/lib/DBIx/Class/Table.pm index 9aa00ab..451b0bd 100644 --- a/lib/DBIx/Class/Table.pm +++ b/lib/DBIx/Class/Table.pm @@ -4,6 +4,7 @@ use strict; use warnings; use DBIx::Class::ResultSet; +use Data::Page; use base qw/Class::Data::Inheritable/; @@ -15,6 +16,8 @@ __PACKAGE__->mk_classdata('table_alias'); # FIXME: Doesn't actually do anything __PACKAGE__->mk_classdata('_resultset_class' => 'DBIx::Class::ResultSet'); +__PACKAGE__->mk_classdata('_page_object'); + sub iterator_class { shift->_resultset_class(@_) } =head1 NAME @@ -112,9 +115,26 @@ sub search { $attrs = { %{ pop(@_) } }; } $attrs->{where} = (@_ == 1 || ref $_[0] eq "HASH" ? shift: {@_}); + + # for pagination, we create the resultset with no limit and slice it later + my $page = {}; + if ( $attrs->{page} ) { + map { $page->{$_} = $attrs->{$_} } qw/rows page/; + delete $attrs->{$_} for qw/rows offset page/; + } my $rs = $class->resultset($attrs); - + + if ( $page->{page} ) { + my $pager = Data::Page->new( + $rs->count, + $page->{rows} || 10, + $page->{page} || 1 ); + $class->_page_object( $pager ); + return $rs->slice( $pager->skipped, + $pager->skipped + $pager->entries_per_page - 1 ); + } + return (wantarray ? $rs->all : $rs); } @@ -175,6 +195,17 @@ sub find_or_create { sub columns { return keys %{shift->_columns}; } +=item page + + $pager = $class->page; + +Returns a Data::Page object for the most recent search that was performed +using the page parameter. + +=cut + +sub page { shift->_page_object } + 1; =back diff --git a/t/07pager.t b/t/07pager.t index 38a290a..04b8b28 100644 --- a/t/07pager.t +++ b/t/07pager.t @@ -7,13 +7,14 @@ use lib qw(t/lib); use_ok('DBICTest'); # first page -my ( $pager, $it ) = DBICTest::CD->page( +my $it = DBICTest::CD->search( {}, { order_by => 'title', rows => 3, page => 1 } ); - +my $pager = DBICTest::CD->page; + is( $pager->entries_on_this_page, 3, "entries_on_this_page ok" ); is( $pager->next_page, 2, "next_page ok" ); @@ -25,38 +26,22 @@ $it->next; is( $it->next, undef, "next past end of page ok" ); -# second page -( $pager, $it ) = DBICTest::CD->page( +# second page, testing with array +my @page2 = DBICTest::CD->search( {}, { order_by => 'title', rows => 3, page => 2 } ); +$pager = DBICTest::CD->page; 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" ); +is( $page2[0]->title, "Generic Manufactured Singles", "second page first title ok" ); # based on a failing criteria submitted by waswas # requires SQL::Abstract >= 1.20 -( $pager, $it ) = DBICTest::CD->page( +$it = DBICTest::CD->search( { title => [ -and => { diff --git a/t/cdbi-t/30-pager.t b/t/cdbi-t/30-pager.t new file mode 100644 index 0000000..aba18e0 --- /dev/null +++ b/t/cdbi-t/30-pager.t @@ -0,0 +1,47 @@ +use strict; +use Test::More; + +BEGIN { + eval "use DBD::SQLite"; + plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 6); +} + +use lib 't/testlib'; +use Film; + +my @film = ( + Film->create({ Title => 'Film 1' }), + Film->create({ Title => 'Film 2' }), + Film->create({ Title => 'Film 3' }), + Film->create({ Title => 'Film 4' }), + Film->create({ Title => 'Film 5' }), +); + +# first page +my ( $pager, $it ) = Film->page( + {}, + { 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, "Film 1", "iterator->next ok" ); + +$it->next; +$it->next; + +is( $it->next, undef, "next past end of page ok" ); + +# second page +( $pager, $it ) = Film->page( + {}, + { rows => 3, + page => 2 } +); + +is( $pager->entries_on_this_page, 2, "entries on second page ok" ); + +is( $it->next->title, "Film 4", "second page first title ok" );