Fix grouped count over a joined resultset with clashing columns
Peter Rabbitson [Sat, 12 Jun 2010 00:16:26 +0000 (02:16 +0200)]
Changes
lib/DBIx/Class/ResultSet.pm
t/71mysql.t

diff --git a/Changes b/Changes
index 6a07924..d03b1e3 100644 (file)
--- a/Changes
+++ b/Changes
@@ -5,6 +5,8 @@ Revision history for DBIx::Class
           column names, so we stay within the 30-char limit (RT#58271)
         - Fix a Storage/$dbh leak introduced by th migration to
           Try::Tiny (this is *not* a Try::Tiny bug)
+        - Fix corner case of count with group-by over a 1:1 join column
+          where the selector ends up with column name clashes
 
     * Misc
         - Test suite default on-disk database now checks for Win32
index e84c83d..004368a 100644 (file)
@@ -1274,6 +1274,8 @@ sub _count_subq_rs {
   # Calculate subquery selector
   if (my $g = $sub_attrs->{group_by}) {
 
+    my $sql_maker = $rsrc->storage->sql_maker;
+
     # necessary as the group_by may refer to aliased functions
     my $sel_index;
     for my $sel (@{$attrs->{select}}) {
@@ -1282,7 +1284,17 @@ sub _count_subq_rs {
     }
 
     for my $g_part (@$g) {
-      push @{$sub_attrs->{select}}, $sel_index->{$g_part} || $g_part;
+      my $colpiece = $sel_index->{$g_part} || $g_part;
+
+      # disqualify join-based group_by's. Arcane but possible query
+      # also horrible horrible hack to alias a column (not a func.)
+      # (probably need to introduce SQLA syntax)
+      if ($colpiece =~ /\./ && $colpiece !~ /^$attrs->{alias}\./) {
+        my $as = $colpiece;
+        $as =~ s/\./__/;
+        $colpiece = \ sprintf ('%s AS %s', map { $sql_maker->_quote ($_) } ($colpiece, $as) );
+      }
+      push @{$sub_attrs->{select}}, $colpiece;
     }
   }
   else {
index 755bbf6..8d5a323 100644 (file)
@@ -250,7 +250,11 @@ NULLINSEARCH: {
 
 # check for proper grouped counts
 {
-  my $ansi_schema = DBICTest::Schema->connect ($dsn, $user, $pass, { on_connect_call => 'set_strict_mode' });
+  my $ansi_schema = DBICTest::Schema->connect ($dsn, $user, $pass, {
+    on_connect_call => 'set_strict_mode',
+    quote_char => '`',
+    name_sep => '.'
+  });
   my $rs = $ansi_schema->resultset('CD');
 
   my $years;
@@ -263,6 +267,14 @@ NULLINSEARCH: {
       'grouped count correct',
     );
   }, 'Grouped count does not throw');
+
+  lives_ok( sub {
+    $ansi_schema->resultset('Owners')->search({}, {
+      join => 'books', group_by => [ 'me.id', 'books.id' ]
+    })->count();
+  }, 'count on grouped columns with the same name does not throw');
+
+
 }
 
 ZEROINSEARCH: {