From: Will Hawes Date: Sat, 28 Jan 2006 18:37:01 +0000 (+0000) Subject: allow count() with GROUP BY X-Git-Tag: v0.05005~81 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class.git;a=commitdiff_plain;h=15c382bed3d8034f368386bd67236b8f342c1f25 allow count() with GROUP BY --- diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index e696555..f3617e7 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -373,17 +373,37 @@ on the resultset and counts the results of that. sub count { my $self = shift; return $self->search(@_)->count if @_ && defined $_[0]; - $self->throw_exception( - "Unable to ->count with a GROUP BY" - ) if defined $self->{attrs}{group_by}; unless (defined $self->{count}) { + my $group_by; + my $select = { 'count' => '*' }; + if( $group_by = delete $self->{attrs}{group_by} ) { + my @distinct = @$group_by; + # todo: try CONCAT for multi-column pk + my @pk = $self->result_source->primary_columns; + if( scalar(@pk) == 1 ) { + my $pk = shift(@pk); + my $alias = $self->{attrs}{alias}; + my $re = qr/^($alias\.)?$pk$/; + foreach my $column ( @$group_by ) { + if( $column =~ $re ) { + @distinct = ( $column ); + last; + } + } + } + + $select = { count => { 'distinct' => \@distinct } }; + #use Data::Dumper; die Dumper $select; + } + my $attrs = { %{ $self->{attrs} }, - select => { 'count' => '*' }, + select => $select, as => [ 'count' ] }; # offset, order by and page are not needed to count. record_filter is cdbi delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/; ($self->{count}) = (ref $self)->new($self->result_source, $attrs)->cursor->next; + $self->{attrs}{group_by} = $group_by; } return 0 unless $self->{count}; my $count = $self->{count}; diff --git a/t/run/16joins.tl b/t/run/16joins.tl index 1b3ff15..14ca4bd 100644 --- a/t/run/16joins.tl +++ b/t/run/16joins.tl @@ -7,7 +7,7 @@ BEGIN { eval "use DBD::SQLite"; plan $@ ? ( skip_all => 'needs DBD::SQLite for testing' ) - : ( tests => 27 ); + : ( tests => 31 ); } # test the abstract join => SQL generator @@ -188,6 +188,23 @@ my @artists = $schema->resultset("Artist")->search({ 'tags.tag' => 'Shiny' }, cmp_ok( @artists, '==', 2, "two-join search ok" ); +$rs = $schema->resultset("CD")->search( + {}, + { group_by => [qw/ title me.cdid /] } +); + +cmp_ok( $rs->count, '==', 5, "count() ok after group_by on main pk" ); + +cmp_ok( scalar $rs->all, '==', 5, "all() returns same count as count() after group_by on main pk" ); + +$rs = $schema->resultset("CD")->search( + {}, + { join => [qw/ artist /], group_by => [qw/ artist.name /] } +); + +cmp_ok( $rs->count, '==', 3, "count() ok after group_by on related column" ); + +cmp_ok( scalar $rs->all, '==', 3, "all() returns same count as count() after group_by on related column" ); } 1;