Properly wrap a subquery around grouped resultsets in case of $rscol->func($func)
Peter Rabbitson [Sat, 23 Feb 2013 15:44:13 +0000 (16:44 +0100)]
Changes
lib/DBIx/Class/ResultSetColumn.pm
t/88result_set_column.t

diff --git a/Changes b/Changes
index 436771f..ae17bab 100644 (file)
--- a/Changes
+++ b/Changes
@@ -19,6 +19,8 @@ Revision history for DBIx::Class
         - Properly consider unselected order_by criteria during complex
           subqueried prefetch
         - Properly support "MySQL-style" left-side group_by with prefetch
+        - Fix $grouped_rs->get_column($col)->func($func) producing incorrect
+          SQL (RT#81127)
 
 0.08209 2013-03-01 12:56 (UTC)
     * New Features / Changes
index 5f37d89..3705d50 100644 (file)
@@ -422,12 +422,19 @@ Creates the resultset that C<func()> uses to run its query.
 
 sub func_rs {
   my ($self,$function) = @_;
-  return $self->{_parent_resultset}->search(
-    undef, {
-      select => {$function => $self->{_select}},
-      as => [$self->{_as}],
-    },
-  );
+
+  my $rs = $self->{_parent_resultset};
+  my $select = $self->{_select};
+
+  # wrap a grouped rs
+  if ($rs->_resolved_attrs->{group_by}) {
+    $select = $self->{_as};
+    $rs = $rs->as_subselect_rs;
+  }
+
+  $rs->search( undef, {
+    columns => { $self->{_as} => { $function => $select } }
+  } );
 }
 
 =head2 throw_exception
index 69eb911..ff8db9e 100644 (file)
@@ -167,4 +167,29 @@ is_same_sql_bind (
   'Correct SQL for prefetch/order_by/group_by'
 );
 
+# test aggregate on a function
+{
+  my $tr_rs = $schema->resultset("Track");
+  $tr_rs->create({ cd => 2, title => 'dealbreaker' });
+
+  is(
+    $tr_rs->get_column('cd')->max,
+    5,
+    "Correct: Max cd in Track is 5"
+  );
+
+  my $track_counts_per_cd_via_group_by = $tr_rs->search({}, {
+    columns => [ 'cd', { cnt => { count => 'trackid', -as => 'cnt' } } ],
+    group_by => 'cd',
+  })->get_column('cnt');
+
+  is ($track_counts_per_cd_via_group_by->max, 4, 'Correct max tracks per cd');
+  is ($track_counts_per_cd_via_group_by->min, 3, 'Correct min tracks per cd');
+  is (
+    sprintf('%0.1f', $track_counts_per_cd_via_group_by->func('avg') ),
+    '3.2',
+    'Correct avg tracks per cd'
+  );
+}
+
 done_testing;