From: André Walker Date: Wed, 13 Feb 2013 15:47:17 +0000 (-0200) Subject: Fix duplicated columns for count() X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=913b4bae66f2a424428ff3bd1e340b42da4581b8;p=dbsrgits%2FDBIx-Class-Historic.git Fix duplicated columns for count() When a same aggregate function was used more than once in a 'having' clause, count() added that function more than once to 'select'. --- diff --git a/Changes b/Changes index c69cc72..5b1d6ea 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,10 @@ Revision history for DBIx::Class + * Fixes + - Fix duplicated selected columns when calling 'count' when a same + aggregate function is used more than once in a 'having' clause + (RT#83305) + 0.08206 2013-02-08 * Fixes - Fix dbh_do() failing to properly reconnect (regression in 0.08205) diff --git a/lib/DBIx/Class.pm b/lib/DBIx/Class.pm index 66fc8a3..eafc15a 100644 --- a/lib/DBIx/Class.pm +++ b/lib/DBIx/Class.pm @@ -303,6 +303,8 @@ amiri: Amiri Barksdale amoore: Andrew Moore +andrewalker: Andre Walker + andyg: Andy Grundman ank: Andres Kievsky diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 545f993..10905b2 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -1591,18 +1591,22 @@ sub _count_subq_rs { my ($lquote, $rquote, $sep) = map { quotemeta $_ } ($sql_maker->_quote_chars, $sql_maker->name_sep); - my $sql = $sql_maker->_parse_rs_attrs ({ having => $attrs->{having} }); + my $having_sql = $sql_maker->_parse_rs_attrs ({ having => $attrs->{having} }); + my %seen_having; # search for both a proper quoted qualified string, for a naive unquoted scalarref # and if all fails for an utterly naive quoted scalar-with-function - while ($sql =~ / + while ($having_sql =~ / $rquote $sep $lquote (.+?) $rquote | [\s,] \w+ \. (\w+) [\s,] | [\s,] $lquote (.+?) $rquote [\s,] /gx) { - push @parts, ($1 || $2 || $3); # one of them matched if we got here + my $part = $1 || $2 || $3; # one of them matched if we got here + unless ($seen_having{$part}++) { + push @parts, $part; + } } } diff --git a/t/count/count_rs.t b/t/count/count_rs.t index 88961c8..83b6257 100644 --- a/t/count/count_rs.t +++ b/t/count/count_rs.t @@ -168,4 +168,42 @@ my $schema = DBICTest->init_schema(); is ($crs->next, 2, 'Correct artist count (each with one 2001 cd)'); } +# count with two having clauses +{ + my $rs = $schema->resultset("Artist")->search( + {}, + { + join => 'cds', + group_by => 'me.artistid', + '+select' => [ { max => 'cds.year', -as => 'newest_cd_year' } ], + '+as' => ['newest_cd_year'], + having => { 'newest_cd_year' => [ '1998', '2001' ] } + } + ); + + my $crs = $rs->count_rs; + + is_same_sql_bind ( + $crs->as_query, + '(SELECT COUNT( * ) + FROM ( + SELECT me.artistid, MAX( cds.year ) AS newest_cd_year + FROM artist me + LEFT JOIN cd cds ON cds.artist = me.artistid + GROUP BY me.artistid + HAVING newest_cd_year = ? OR newest_cd_year = ? + ) me + )', + [ + [ { dbic_colname => 'newest_cd_year' } + => '1998' ], + [ { dbic_colname => 'newest_cd_year' } + => '2001' ], + ], + 'count with having clause keeps sql as alias', + ); + + is ($crs->next, 3, 'Correct artist count (each with one 1998 or 2001 cd)'); +} + done_testing;