diff --git a/Civi/Api4/Query/Api4SelectQuery.php b/Civi/Api4/Query/Api4SelectQuery.php index b8240078b9cc..c1c748c18ce8 100644 --- a/Civi/Api4/Query/Api4SelectQuery.php +++ b/Civi/Api4/Query/Api4SelectQuery.php @@ -452,9 +452,13 @@ protected function composeClause(array $clause, string $type, int $depth) { // For WHERE clause, expr must be the name of a field. if ($type === 'WHERE' && !$isExpression) { - $field = $this->getField($expr, TRUE); - FormattingUtil::formatInputValue($value, $expr, $field, $operator); - $fieldAlias = $this->getExpression($expr)->render($this->apiFieldSpec); + $expr = $this->getExpression($expr, ['SqlField', 'SqlFunction']); + if ($expr->getType() === 'SqlField') { + $fieldName = count($expr->getFields()) === 1 ? $expr->getFields()[0] : NULL; + $field = $this->getField($fieldName, TRUE); + FormattingUtil::formatInputValue($value, $fieldName, $field, $operator); + } + $fieldAlias = $expr->render($this->apiFieldSpec); } // For HAVING, expr must be an item in the SELECT clause elseif ($type === 'HAVING') { @@ -592,11 +596,12 @@ protected function createSQLClause($fieldAlias, $operator, $value, $field, int $ /** * @param string $expr + * @param array $allowedTypes * @return SqlExpression * @throws \API_Exception */ - protected function getExpression(string $expr) { - $sqlExpr = SqlExpression::convert($expr); + protected function getExpression(string $expr, $allowedTypes = NULL) { + $sqlExpr = SqlExpression::convert($expr, FALSE, $allowedTypes); foreach ($sqlExpr->getFields() as $fieldName) { $this->getField($fieldName, TRUE); } diff --git a/tests/phpunit/api/v4/Action/SqlFunctionTest.php b/tests/phpunit/api/v4/Action/SqlFunctionTest.php index 59300c369205..b87873ee6aa9 100644 --- a/tests/phpunit/api/v4/Action/SqlFunctionTest.php +++ b/tests/phpunit/api/v4/Action/SqlFunctionTest.php @@ -262,4 +262,23 @@ public function testRandFunction() { $this->assertLessThan(1, $result[0]['rand']); } + public function testYearInWhereClause() { + $lastName = uniqid(__FUNCTION__); + $sampleData = [ + ['first_name' => 'abc', 'last_name' => $lastName, 'birth_date' => '2009-11-11'], + ['first_name' => 'def', 'last_name' => $lastName, 'birth_date' => '2009-01-01'], + ['first_name' => 'def', 'last_name' => $lastName, 'birth_date' => '2010-01-01'], + ]; + Contact::save(FALSE) + ->setRecords($sampleData) + ->execute(); + + $result = Contact::get(FALSE) + ->addWhere('last_name', '=', $lastName) + ->addWhere('YEAR(birth_date)', '=', 2009) + ->selectRowCount() + ->execute(); + $this->assertCount(2, $result); + } + }