From: Rafael Kitover Date: Thu, 4 Jun 2009 16:03:01 +0000 (+0000) Subject: use TOP for sybase limit count thanks to refactored count X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a0348159b9bce5f85073373a8885f405015c899f;p=dbsrgits%2FDBIx-Class-Historic.git use TOP for sybase limit count thanks to refactored count --- diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index 0141e1c..cee87a7 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -1252,7 +1252,7 @@ sub _trim_attributes_for_count { # take off any column specs, any pagers, record_filter is cdbi, and no point of ordering a count delete @attrs{qw/ columns +columns select +select as +as rows offset page pager order_by - record_filter/)}; + record_filter/}; return \%attrs; } diff --git a/lib/DBIx/Class/Storage/DBI/Sybase.pm b/lib/DBIx/Class/Storage/DBI/Sybase.pm index e5acf8d..c68cfd6 100644 --- a/lib/DBIx/Class/Storage/DBI/Sybase.pm +++ b/lib/DBIx/Class/Storage/DBI/Sybase.pm @@ -3,6 +3,7 @@ package DBIx::Class::Storage::DBI::Sybase; use strict; use warnings; +use Class::C3; use base qw/DBIx::Class::Storage::DBI/; use Carp::Clan qw/^DBIx::Class/; @@ -63,25 +64,34 @@ sub count { my ($self, $source, $attrs) = @_; if (exists $attrs->{rows}) { + my $offset = $attrs->{offset} || 0; + my $total = $attrs->{rows} + $offset; + my $new_attrs = $self->_trim_attributes_for_count($source, $attrs); - $new_attrs->{select} = '1'; - $new_attrs->{as} = ['dummy']; + my $query = $source->resultset_class->new($source, $new_attrs)->as_query; -# speed things up at least *a little* - $new_attrs->{result_class} = 'DBIx::Class::ResultClass::HashRefInflator'; + my $top_attrs = {}; + $top_attrs->{from} = [{ + top_subq => $query + }]; + $top_attrs->{select} = "TOP $total 1"; + $top_attrs->{as} = ['total']; - my $offset = $attrs->{offset} || 0; - my $total = $attrs->{rows} + $offset; - - $self->dbh->do("set rowcount $total"); + my $top_query = $source->resultset_class->new($source, $top_attrs)->as_query; + + my $count_attrs = {}; + $count_attrs->{from} = [{ + count_subq => $top_query + }]; + $count_attrs->{select} = { count => '*' }; + $count_attrs->{as} = ['count']; - my $tmp_rs = $source->resultset_class->new($source, $new_attrs); - - my $count = 0; - $count++ while $tmp_rs->cursor->next; + my $tmp_rs = $source->resultset_class->new($source, $count_attrs); + my ($count) = $tmp_rs->cursor->next; - $self->dbh->do("set rowcount 0"); + $count -= $offset; + $count = $attrs->{rows} if $count > $attrs->{rows}; return $count; } diff --git a/t/746sybase.t b/t/746sybase.t index 3a4ebb9..ec5e53e 100644 --- a/t/746sybase.t +++ b/t/746sybase.t @@ -11,7 +11,7 @@ my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_SYBASE_${_}" } qw/DSN USER PASS/} plan skip_all => 'Set $ENV{DBICTEST_SYBASE_DSN}, _USER and _PASS to run this test' unless ($dsn && $user); -plan tests => 20*2; +plan tests => (16 + 4*2)*2; my @storage_types = ( 'DBI::Sybase', @@ -77,8 +77,22 @@ SQL is( $it->next->name, "Artist 2", "iterator->next ok" ); is( $it->next, undef, "next past end of resultset ok" ); +# now try with offset + $it = $schema->resultset('Artist')->search({}, { + rows => 3, + offset => 3, + order_by => 'artistid', + }); + + is( $it->count, 3, "LIMIT with offset count ok" ); + + is( $it->next->name, "Artist 3", "iterator->next ok" ); + $it->next; + is( $it->next->name, "Artist 5", "iterator->next ok" ); + is( $it->next, undef, "next past end of resultset ok" ); + SKIP: { - skip 'quoting bug with NoBindVars', 8 + skip 'quoting bug with NoBindVars', 4*2 if $storage_type eq 'DBI::Sybase::NoBindVars'; # Test DateTime inflation with DATETIME