From 2764750785fce1c3678e7fb9766496dc5e91363f Mon Sep 17 00:00:00 2001 From: JoostK Date: Tue, 24 Mar 2015 12:50:13 +0100 Subject: [PATCH] Extend aggregate support with groupings --- src/Illuminate/Database/Query/Builder.php | 32 ++++++++++--------- tests/Database/DatabaseQueryBuilderTest.php | 34 +++++++++++++++++++++ 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 9344f284447a..6743d2c81c1e 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -1428,10 +1428,7 @@ public function getCountForPagination() $total = $this->count(); - if(isset($this->groups)) - { - $total = count($total); - } + if (is_array($total)) $total = count($total); $this->restoreFieldsForCount(); @@ -1576,7 +1573,9 @@ public function count($columns = '*') $columns = array($columns); } - return $this->aggregate(__FUNCTION__, $columns); + $count = $this->aggregate(__FUNCTION__, $columns); + + return is_array($count) ? array_map('intval', $count) : (int) $count; } /** @@ -1647,20 +1646,23 @@ public function aggregate($function, $columns = array('*')) $this->columns = $previousColumns; - // Once we have used groupBy function, $result may have more than one - // record, so we need to get all of $results elements in array. - if (count($results) > 1) + $results = array_map(function($result) { - $results = array_change_key_case((array) $results); + $result = array_change_key_case((array) $result); - return array_pluck($results, 'aggregate'); - } + return $result['aggregate']; + }, (array) $results); - if (isset($results[0])) + // If any groupings have been specified, we return the aggregate results as + // is such that we give information about all groups. Otherwise we check + // if the aggregate had any results and return the value as a scalar. + if (isset($this->groups)) { - $result = array_change_key_case((array) $results[0]); - - return $result['aggregate']; + return $results; + } + elseif (isset($results[0])) + { + return $results[0]; } } diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 1f44e614c494..b151d8232471 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -810,6 +810,12 @@ public function testAggregateFunctions() $results = $builder->from('users')->count(); $this->assertEquals(1, $results); + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', array(), true)->andReturn(null); + $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); + $results = $builder->from('users')->count(); + $this->assertEquals(0, $results); + $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users" limit 1', array(), true)->andReturn(array(array('aggregate' => 1))); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); @@ -836,6 +842,34 @@ public function testAggregateFunctions() } + public function testAggregateFunctionsWithGroups() + { + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users" group by "name"', array(), true)->andReturn(array(array('aggregate' => '3'), array('Aggregate' => '2'))); + $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); + $results = $builder->from('users')->groupBy('name')->count(); + $this->assertSame(array(3, 2), $results); + + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('select')->once()->with('select max("id") as aggregate from "users" group by "name"', array(), true)->andReturn(array(array('aggregate' => 3), array('aggregate' => 2))); + $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); + $results = $builder->from('users')->groupBy('name')->max('id'); + $this->assertEquals(array(3, 2), $results); + + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('select')->once()->with('select min("id") as aggregate from "users" group by "name"', array(), true)->andReturn(array(array('aggregate' => 3), array('aggregate' => 2))); + $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); + $results = $builder->from('users')->groupBy('name')->min('id'); + $this->assertEquals(array(3, 2), $results); + + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users" group by "name"', array(), true)->andReturn(array(array('aggregate' => 3), array('aggregate' => 2))); + $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function($builder, $results) { return $results; }); + $results = $builder->from('users')->groupBy('name')->sum('id'); + $this->assertEquals(array(3, 2), $results); + } + + public function testAggregateResetFollowedByGet() { $builder = $this->getBuilder();