From: Peter Rabbitson Date: Thu, 4 Jun 2009 11:38:21 +0000 (-0700) Subject: Merge 'trunk' into 'sybase' X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=ec10b4644f46ea1b51fe4be0addff6831cc3a267;hp=-c;p=dbsrgits%2FDBIx-Class-Historic.git Merge 'trunk' into 'sybase' r5334@hlagh (orig r6501): ribasushi | 2009-06-04 06:38:21 -0700 Really delegate counting to the storage class - now we have either a grouped count or a regular one --- ec10b4644f46ea1b51fe4be0addff6831cc3a267 diff --combined lib/DBIx/Class/Storage/DBI.pm index f3ea456,c20a931..0141e1c --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@@ -926,22 -926,6 +926,22 @@@ sub _fix_bind_params } @bind; } +sub _flatten_bind_params { + my ($self, @bind) = @_; + + ### Turn @bind from something like this: + ### ( [ "artist", 1 ], [ "cdid", 1, 3 ] ) + ### to this: + ### ( 1, 1, 3 ) + return + map { + if ( defined( $_ && $_->[1] ) ) { + @{$_}[ 1 .. $#$_ ]; + } + else { undef; } + } @bind; +} + sub _query_start { my ( $self, $sql, @bind ) = @_; @@@ -1245,30 -1229,57 +1245,66 @@@ sub _select_args return @args; } -sub count { +sub _trim_attributes_for_count { my ($self, $source, $attrs) = @_; - - my $tmp_attrs = { %$attrs }; + my %attrs = %$attrs; # take off any column specs, any pagers, record_filter is cdbi, and no point of ordering a count - delete $attrs{$_} for (qw/columns +columns select +select as +as rows offset page pager order_by record_filter/); - delete $tmp_attrs->{$_} for (qw/columns +columns select +select as +as rows offset page pager order_by record_filter/); ++ delete @attrs{qw/ ++ columns +columns select +select as +as rows offset page pager order_by ++ record_filter/)}; + + return \%attrs; +} + +sub count { + my ($self, $source, $attrs) = @_; + + my $new_attrs = $self->_trim_attributes_for_count($source, $attrs); - $tmp_attrs->{select} = { count => '*' }; - $tmp_attrs->{as} = [qw/count/]; + $new_attrs->{select} = { count => '*' }; + $new_attrs->{as} = [qw/count/]; - my $tmp_rs = $source->resultset_class->new($source, $tmp_attrs); + my $tmp_rs = $source->resultset_class->new($source, $new_attrs); my ($count) = $tmp_rs->cursor->next; + # if the offset/rows attributes are still present, we did not use + # a subquery, so we need to make the calculations in software + $count -= $attrs->{offset} if $attrs->{offset}; + $count = $attrs->{rows} if $attrs->{rows} and $attrs->{rows} < $count; + $count = 0 if ($count < 0); + return $count; } + sub count_grouped { + my ($self, $source, $attrs) = @_; + + # copy for the subquery, we need to do some adjustments to it too + my $sub_attrs = { %$attrs }; + + # these can not go in the subquery, and there is no point of ordering it + delete $sub_attrs->{$_} for qw/prefetch collapse select +select as +as columns +columns order_by/; + + # if we prefetch, we group_by primary keys only as this is what we would get out of the rs via ->next/->all + # simply deleting group_by suffices, as the code below will re-fill it + # Note: we check $attrs, as $sub_attrs has collapse deleted + if (ref $attrs->{collapse} and keys %{$attrs->{collapse}} ) { + delete $sub_attrs->{group_by}; + } + + $sub_attrs->{columns} = $sub_attrs->{group_by} ||= [ map { "$attrs->{alias}.$_" } ($source->primary_columns) ]; + + $attrs->{from} = [{ + count_subq => $source->resultset_class->new ($source, $sub_attrs )->as_query + }]; + + # the subquery replaces this + delete $attrs->{$_} for qw/where bind prefetch collapse distinct group_by having having_bind rows offset page pager/; + + return $self->count ($source, $attrs); + } + sub source_bind_attributes { my ($self, $source) = @_;