From: Peter Rabbitson Date: Mon, 16 Nov 2009 07:11:17 +0000 (+0000) Subject: Fix order_by/distinct bug X-Git-Tag: v0.08116~138^2 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=886d0b493b278549be31c6d2db1ba27a43997536;p=dbsrgits%2FDBIx-Class.git Fix order_by/distinct bug --- diff --git a/Changes b/Changes index 0f2dead..8fe5fa2 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,8 @@ Revision history for DBIx::Class + - Fix distinct => 1 with non-selecting order_by (the columns + in order_by also need to be aded to the resulting group_by) + 0.08114 2009-11-14 17:45:00 (UTC) - Preliminary support for MSSQL via DBD::ADO - Fix botched 0.08113 release (invalid tarball) diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 61b2a16..54f1cac 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -2820,6 +2820,22 @@ sub _resolved_attrs { } else { $attrs->{group_by} = [ grep { !ref($_) || (ref($_) ne 'HASH') } @{$attrs->{select}} ]; + + # add any order_by parts that are not already present in the group_by + # we need to be careful not to add any named functions/aggregates + # i.e. select => [ ... { count => 'foo', -as 'foocount' } ... ] + my %already_grouped = map { $_ => 1 } (@{$attrs->{group_by}}); + + my $storage = $self->result_source->schema->storage; + my $rs_column_list = $storage->_resolve_column_info ($attrs->{from}); + my @chunks = $storage->sql_maker->_order_by_chunks ($attrs->{order_by}); + + for my $chunk (map { ref $_ ? @$_ : $_ } (@chunks) ) { + $chunk =~ s/\s+ (?: ASC|DESC ) \s* $//ix; + if ($rs_column_list->{$chunk} && not $already_grouped{$chunk}++) { + push @{$attrs->{group_by}}, $chunk; + } + } } } diff --git a/t/prefetch/grouped.t b/t/prefetch/grouped.t index f6fabae..a7a16e0 100644 --- a/t/prefetch/grouped.t +++ b/t/prefetch/grouped.t @@ -221,7 +221,7 @@ for ($cd_rs->all) { FROM ( SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me - GROUP BY me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track + GROUP BY me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track, cdid ORDER BY cdid ) me LEFT JOIN tags tags ON tags.cd = me.cdid @@ -341,14 +341,15 @@ for ($cd_rs->all) { } ); is_same_sql_bind($rs->as_query, q{ - SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track, me.test_count, tags.tagid, tags.cd, tags.tag - FROM (SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track, COUNT( tags.tag ) AS test_count + (SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track, me.test_count, tags.tagid, tags.cd, tags.tag + FROM (SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track, COUNT( tags.tag ) AS test_count FROM cd me LEFT JOIN tags tags ON tags.cd = me.cdid GROUP BY me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track, tags.tag ORDER BY tags.tag ASC LIMIT 1) me - LEFT JOIN tags tags ON tags.cd = me.cdid - ORDER BY tags.tag ASC, tags.cd, tags.tag + LEFT JOIN tags tags ON tags.cd = me.cdid + ORDER BY tags.tag ASC, tags.cd, tags.tag + ) }, []); }