Skip to content
Snippets Groups Projects
Unverified Commit e01862dd authored by colemanw's avatar colemanw Committed by GitHub
Browse files

Merge pull request #21301 from greenpeace-cee/add-where-functions

Add SqlFunction support in addWhere 
parents 49d2b8cf 1f76bc10
No related branches found
No related tags found
No related merge requests found
......@@ -123,6 +123,22 @@ class DAOGetAction extends AbstractGetAction {
}
}
/**
* @param string $fieldName
* @param string $op
* @param mixed $value
* @param bool $isExpression
* @return $this
* @throws \API_Exception
*/
public function addWhere(string $fieldName, string $op, $value = NULL, bool $isExpression = FALSE) {
if (!in_array($op, CoreUtil::getOperators())) {
throw new \API_Exception('Unsupported operator');
}
$this->where[] = [$fieldName, $op, $value, $isExpression];
return $this;
}
/**
* @return array
*/
......
......@@ -431,7 +431,7 @@ class Api4SelectQuery {
/**
* Validate and transform a leaf clause array to SQL.
* @param array $clause [$fieldName, $operator, $criteria]
* @param array $clause [$fieldName, $operator, $criteria, $isExpression]
* @param string $type
* WHERE|HAVING|ON
* @param int $depth
......@@ -443,12 +443,13 @@ class Api4SelectQuery {
$field = NULL;
// Pad array for unary operators
[$expr, $operator, $value] = array_pad($clause, 3, NULL);
$isExpression = $clause[3] ?? FALSE;
if (!in_array($operator, CoreUtil::getOperators(), TRUE)) {
throw new \API_Exception('Illegal operator');
}
// For WHERE clause, expr must be the name of a field.
if ($type === 'WHERE') {
if ($type === 'WHERE' && !$isExpression) {
$field = $this->getField($expr, TRUE);
FormattingUtil::formatInputValue($value, $expr, $field, $operator);
$fieldAlias = $this->getExpression($expr)->render($this->apiFieldSpec);
......@@ -491,7 +492,7 @@ class Api4SelectQuery {
}
$fieldAlias = '`' . $fieldAlias . '`';
}
elseif ($type === 'ON') {
elseif ($type === 'ON' || ($type === 'WHERE' && $isExpression)) {
$expr = $this->getExpression($expr);
$fieldName = count($expr->getFields()) === 1 ? $expr->getFields()[0] : NULL;
$fieldAlias = $expr->render($this->apiFieldSpec);
......
<?php
/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
namespace Civi\Api4\Query;
/**
* Sql function
*/
class SqlFunctionBINARY extends SqlFunction {
protected static $category = self::CATEGORY_STRING;
protected static function params(): array {
return [
[
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlString'],
],
];
}
/**
* @return string
*/
public static function getTitle(): string {
return ts('Binary');
}
}
......@@ -261,6 +261,26 @@ class ContactGetTest extends \api\v4\UnitTestCase {
$this->assertEquals(['Student'], $result['Contact_RelationshipCache_Contact_01.contact_sub_type:label']);
}
public function testGetWithWhereExpression() {
$last_name = uniqid(__FUNCTION__);
$alice = Contact::create()
->setValues(['first_name' => 'Alice', 'last_name' => $last_name])
->execute()->first();
$result = Contact::get(FALSE)
->addWhere('last_name', '=', $last_name)
->addWhere('LOWER(first_name)', '=', "BINARY('ALICE')", TRUE)
->execute()->indexBy('id');
$this->assertCount(0, $result);
$result = Contact::get(FALSE)
->addWhere('last_name', '=', $last_name)
->addWhere('LOWER(first_name)', '=', "BINARY('alice')", TRUE)
->execute()->indexBy('id');
$this->assertArrayHasKey($alice['id'], (array) $result);
}
/**
* @throws \API_Exception
*/
......
......@@ -426,4 +426,19 @@ class FkJoinTest extends UnitTestCase {
$this->assertStringContainsString("Deprecated join alias 'contact' used in APIv4 get. Should be changed to 'contact_id'", $message);
}
public function testJoinWithExpression() {
Phone::create(FALSE)
->setValues(['contact_id' => $this->getReference('test_contact_1')['id'], 'phone' => '654321'])
->execute();
$contacts = Contact::get(FALSE)
->addSelect('id', 'phone.phone')
->addJoin('Phone', 'INNER', ['LOWER(phone.phone)', '=', "CONCAT('6', '5', '4', '3', '2', '1')"])
->addWhere('id', 'IN', [$this->getReference('test_contact_1')['id'], $this->getReference('test_contact_2')['id']])
->addOrderBy('phone.id')
->execute();
$this->assertCount(1, $contacts);
$this->assertEquals($this->getReference('test_contact_1')['id'], $contacts[0]['id']);
$this->assertEquals('654321', $contacts[0]['phone.phone']);
}
}
......@@ -131,6 +131,20 @@ class SqlFunctionTest extends UnitTestCase {
$this->assertEquals(100, $result[0]['MIN:total_amount']);
$this->assertEquals(2, $result[0]['count']);
$this->assertEquals(1, $result[1]['count']);
$result = Contribution::get(FALSE)
->addGroupBy('contact_id')
->addGroupBy('receive_date')
->addSelect('contact_id')
->addSelect('receive_date')
->addSelect('SUM(total_amount)')
->addOrderBy('receive_date')
->addWhere('contact_id', '=', $cid)
->addHaving('SUM(total_amount)', '>', 300)
->execute();
$this->assertCount(1, $result);
$this->assertStringStartsWith('2020-04-04', $result[0]['receive_date']);
$this->assertEquals(400, $result[0]['SUM:total_amount']);
}
public function testComparisonFunctions() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment