Fix order_by/distinct bug
Peter Rabbitson [Mon, 16 Nov 2009 07:11:17 +0000 (07:11 +0000)]
Changes
lib/DBIx/Class/ResultSet.pm
t/prefetch/grouped.t

diff --git a/Changes b/Changes
index 0f2dead..8fe5fa2 100644 (file)
--- 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)
index 61b2a16..54f1cac 100644 (file)
@@ -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;
+        }
+      }
     }
   }
 
index f6fabae..a7a16e0 100644 (file)
@@ -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
+        )
     }, []);
 }