Skip to content
Snippets Groups Projects
Unverified Commit be12b751 authored by Eileen McNaughton's avatar Eileen McNaughton Committed by GitHub
Browse files

Merge pull request #19755 from eileenmcnaughton/sum_api

#2415 Add api support for aggregate without group by
parents f1730821 cc4c8d1d
Branches
Tags
No related merge requests found
......@@ -88,7 +88,7 @@ class Api4SelectQuery {
$this->api = $apiGet;
// Always select ID of main table unless grouping by something else
$this->forceSelectId = !$this->getGroupBy() || $this->getGroupBy() === ['id'];
$this->forceSelectId = !$this->isAggregateQuery() || $this->getGroupBy() === ['id'];
// Build field lists
foreach ($this->api->entityFields() as $field) {
......@@ -108,6 +108,19 @@ class Api4SelectQuery {
$this->addExplicitJoins();
}
protected function isAggregateQuery() {
if ($this->getGroupBy()) {
return TRUE;
}
foreach ($this->getSelect() as $sql) {
$classname = get_class(SqlExpression::convert($sql, TRUE));
if (method_exists($classname, 'getCategory') && $classname::getCategory() === SqlFunction::CATEGORY_AGGREGATE) {
return TRUE;
}
}
return FALSE;
}
/**
* Builds main final sql statement after initialization.
*
......@@ -381,7 +394,7 @@ class Api4SelectQuery {
*/
protected function composeClause(array $clause, string $type) {
// Pad array for unary operators
list($expr, $operator, $value) = array_pad($clause, 3, NULL);
[$expr, $operator, $value] = array_pad($clause, 3, NULL);
if (!in_array($operator, CoreUtil::getOperators(), TRUE)) {
throw new \API_Exception('Illegal operator');
}
......
......@@ -22,6 +22,7 @@ namespace api\v4\Action;
use api\v4\UnitTestCase;
use Civi\Api4\Activity;
use Civi\Api4\Contact;
use Civi\Test\CiviEnvBuilder;
/**
* @group headless
......@@ -31,22 +32,27 @@ use Civi\Api4\Contact;
*/
class ComplexQueryTest extends UnitTestCase {
public function setUpHeadless() {
public function setUpHeadless(): CiviEnvBuilder {
$this->loadDataSet('DefaultDataSet');
return parent::setUpHeadless();
}
public function tearDown(): void {
$relatedTables = [
'civicrm_activity',
'civicrm_activity_contact',
];
$this->cleanup(['tablesToTruncate' => $relatedTables]);
$this->loadDataSet('DefaultDataSet');
return parent::setUpHeadless();
parent::tearDown();
}
/**
* Fetch all phone call activities
* Expects at least one activity loaded from the data set.
*
* @throws \API_Exception
*/
public function testGetAllHousingSupportActivities() {
public function testGetAllHousingSupportActivities(): void {
$results = Activity::get(FALSE)
->addWhere('activity_type_id:name', '=', 'Phone Call')
->execute();
......
......@@ -34,15 +34,19 @@ use Civi\Api4\Tag;
class FkJoinTest extends UnitTestCase {
public function setUpHeadless() {
$this->loadDataSet('DefaultDataSet');
return parent::setUpHeadless();
}
public function tearDown() {
$relatedTables = [
'civicrm_activity',
'civicrm_phone',
'civicrm_activity_contact',
];
$this->cleanup(['tablesToTruncate' => $relatedTables]);
$this->loadDataSet('DefaultDataSet');
return parent::setUpHeadless();
parent::tearDown();
}
/**
......
......@@ -19,6 +19,7 @@
namespace api\v4\Query;
use Civi\API\Request;
use Civi\Api4\Query\Api4SelectQuery;
use api\v4\UnitTestCase;
......@@ -50,7 +51,7 @@ class Api4SelectQueryTest extends UnitTestCase {
$phoneNum = $this->getReference('test_phone_1')['phone'];
$contact = $this->getReference('test_contact_1');
$api = \Civi\API\Request::create('Phone', 'get', [
$api = Request::create('Phone', 'get', [
'version' => 4,
'checkPermissions' => FALSE,
'select' => ['id', 'phone', 'contact.display_name', 'contact.first_name'],
......@@ -64,8 +65,30 @@ class Api4SelectQueryTest extends UnitTestCase {
$this->assertEquals($contact['display_name'], $firstResult['contact.display_name']);
}
public function testInvaidSort() {
$api = \Civi\API\Request::create('Contact', 'get', [
/**
* @throws \API_Exception
* @throws \CRM_Core_Exception
* @throws \Civi\API\Exception\NotImplementedException
*/
public function testAggregateNoGroupBy(): void {
$api = Request::create('Pledge', 'get', [
'version' => 4,
'checkPermissions' => FALSE,
'select' => ['SUM(amount) AS SUM_amount'],
]);
$query = new Api4SelectQuery($api);
$this->assertEquals(
'SELECT SUM(`a`.`amount`) AS `SUM_amount`
FROM civicrm_pledge a',
trim($query->getSql())
);
}
/**
* @throws \Civi\API\Exception\NotImplementedException
*/
public function testInvalidSort(): void {
$api = Request::create('Contact', 'get', [
'version' => 4,
'checkPermissions' => FALSE,
'select' => ['id', 'display_name'],
......@@ -74,12 +97,13 @@ class Api4SelectQueryTest extends UnitTestCase {
]);
$query = new Api4SelectQuery($api);
try {
$results = $query->run();
$query->run();
$this->fail('An Exception Should have been raised');
}
catch (\API_Exception $e) {
}
$api = \Civi\API\Request::create('Contact', 'get', [
$api = Request::create('Contact', 'get', [
'version' => 4,
'checkPermissions' => FALSE,
'select' => ['id', 'display_name'],
......@@ -88,7 +112,7 @@ class Api4SelectQueryTest extends UnitTestCase {
]);
$query = new Api4SelectQuery($api);
try {
$results = $query->run();
$query->run();
$this->fail('An Exception Should have been raised');
}
catch (\API_Exception $e) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment