From: Peter Rabbitson Date: Tue, 19 May 2009 16:11:00 +0000 (+0000) Subject: Make select always equal group by on count subqueries X-Git-Tag: v0.08103~64^2~2 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=cbf053ae1fbd1f0c0b746d468b7535ae59769423;p=dbsrgits%2FDBIx-Class.git Make select always equal group by on count subqueries Make sure offset does not increment boundlessly on every _resolved_attrs run --- diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 8f2d506..42b100a 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -1150,7 +1150,7 @@ on the resultset and counts the results of that. =cut -my @count_via_subq_attrs = qw/join seen_join group_by/; +my @count_via_subq_attrs = qw/join seen_join prefetch group_by/; sub count { my $self = shift; return $self->search(@_)->count if @_ and defined $_[0]; @@ -1173,14 +1173,21 @@ sub _count_subq { my $attrs = { %{$self->_resolved_attrs} }; - my $select_cols = $attrs->{group_by} || [ map { "$attrs->{alias}.$_" } ($self->result_source->primary_columns) ]; + # copy for the subquery, we need to do some adjustments to it too + my $sub_attrs = { %$attrs }; + + # these can not go in the subquery either + delete $sub_attrs->{$_} for qw/prefetch select +select as +as columns +columns/; + + # force a group_by and the same set of columns (most databases require this) + $sub_attrs->{columns} = $sub_attrs->{group_by} ||= [ map { "$attrs->{alias}.$_" } ($self->result_source->primary_columns) ]; + $attrs->{from} = [{ - count_subq => $self->search ({}, { columns => $select_cols, group_by => $select_cols }) - ->as_query + count_subq => (ref $self)->new ($self->result_source, $sub_attrs )->as_query }]; - # the subquery above will integrate everything, including 'where' and any pagers - delete $attrs->{$_} for (@count_via_subq_attrs, qw/where rows offset pager page/ ); + # the subquery replaces this + delete $attrs->{where}; return $self->__count ($attrs); } @@ -1205,12 +1212,13 @@ sub __count { $attrs ||= { %{$self->{attrs}} }; + # take off any subquery attrs (they'd be incorporated in the subquery), + # any column specs, any pagers, record_filter is cdbi, and no point of ordering a count + delete $attrs->{$_} for (@count_via_subq_attrs, qw/columns +columns select +select as +as rows offset page pager order_by record_filter/); + $attrs->{select} = { count => '*' }; $attrs->{as} = [qw/count/]; - # take off any pagers, record_filter is cdbi, and no point of ordering a count - delete $attrs->{$_} for qw/rows offset page pager order_by record_filter/; - my $tmp_rs = (ref $self)->new($self->result_source, $attrs); my ($count) = $tmp_rs->cursor->next; @@ -2582,9 +2590,8 @@ sub _resolved_attrs { } $attrs->{collapse} = $collapse; - if ( $attrs->{page} ) { - $attrs->{offset} ||= 0; - $attrs->{offset} += ( $attrs->{rows} * ( $attrs->{page} - 1 ) ); + if ( $attrs->{page} and not defined $attrs->{offset} ) { + $attrs->{offset} = ( $attrs->{rows} * ( $attrs->{page} - 1 ) ); } return $self->{_attrs} = $attrs;