diff --git a/application/Espo/ORM/QueryComposer/BaseQueryComposer.php b/application/Espo/ORM/QueryComposer/BaseQueryComposer.php index 59dcf52a51..2ca5195b80 100644 --- a/application/Espo/ORM/QueryComposer/BaseQueryComposer.php +++ b/application/Espo/ORM/QueryComposer/BaseQueryComposer.php @@ -96,18 +96,27 @@ abstract class BaseQueryComposer implements QueryComposer protected const EXISTS_OPERATOR = 'EXISTS'; + /** @var string[] */ + private array $comparisonOperators = [ + '!=s', + '=s', + '!=', + '!*', + '*', + '>=', + '<=', + '>', + '<', + '=', + ]; + /** @var array */ - protected array $comparisonOperators = [ + protected array $comparisonOperatorMap = [ '!=s' => 'NOT IN', '=s' => 'IN', '!=' => '<>', '!*' => 'NOT LIKE', '*' => 'LIKE', - '>=' => '>=', - '<=' => '<=', - '>' => '>', - '<' => '<', - '=' => '=', ]; /** @var array */ @@ -2350,6 +2359,30 @@ abstract class BaseQueryComposer implements QueryComposer return implode(" " . $sqlOp . " ", $wherePartList); } + /** + * @return array{string, string, string} + */ + private function splitWhereLeftItem(string $item): array + { + if (preg_match('/^[a-z0-9]+$/i', $item)) { + return [$item, '=', '=']; + } + + foreach ($this->comparisonOperators as $operator) { + $sqlOperator = $this->comparisonOperatorMap[$operator] ?? $operator; + + if (!str_ends_with($item, $operator)) { + continue; + } + + $expression = trim(substr($item, 0, -strlen($operator))); + + return [$expression, $sqlOperator, $operator]; + } + + return [$item, '=', '=']; + } + /** * @param array $params */ @@ -2410,21 +2443,7 @@ abstract class BaseQueryComposer implements QueryComposer $isNotValue = true; } - $operator = '='; - $operatorOrm = '='; - - if (!preg_match('/^[a-z0-9]+$/i', $field)) { - foreach ($this->comparisonOperators as $op => $opDb) { - if (str_ends_with($field, $op)) { - $field = trim(substr($field, 0, -strlen($op))); - - $operatorOrm = $op; - $operator = $opDb; - - break; - } - } - } + [$field, $operator, $operatorOrm] = $this->splitWhereLeftItem($field); $leftPart = null; @@ -2946,8 +2965,6 @@ abstract class BaseQueryComposer implements QueryComposer return $sql; } - $operator = '='; - $isNotValue = false; $isComplex = false; @@ -2956,16 +2973,7 @@ abstract class BaseQueryComposer implements QueryComposer $isNotValue = true; } - if (!preg_match('/^[a-z0-9]+$/i', $left)) { - foreach ($this->comparisonOperators as $op => $opDb) { - if (str_ends_with($left, $op)) { - $left = trim(substr($left, 0, -strlen($op))); - $operator = $opDb; - - break; - } - } - } + [$left, $operator] = $this->splitWhereLeftItem($left); if (Util::isComplexExpression($left)) { $isComplex = true; diff --git a/application/Espo/ORM/QueryComposer/Functions.php b/application/Espo/ORM/QueryComposer/Functions.php index 6f439b81af..a09cb48cad 100644 --- a/application/Espo/ORM/QueryComposer/Functions.php +++ b/application/Espo/ORM/QueryComposer/Functions.php @@ -29,6 +29,9 @@ namespace Espo\ORM\QueryComposer; +/** + * @internal + */ class Functions { public const FUNCTION_LIST = [ diff --git a/application/Espo/ORM/QueryComposer/PostgresqlQueryComposer.php b/application/Espo/ORM/QueryComposer/PostgresqlQueryComposer.php index d075dbb56e..afe15418ea 100644 --- a/application/Espo/ORM/QueryComposer/PostgresqlQueryComposer.php +++ b/application/Espo/ORM/QueryComposer/PostgresqlQueryComposer.php @@ -49,17 +49,12 @@ class PostgresqlQueryComposer extends BaseQueryComposer protected int $aliasMaxLength = 128; /** @var array */ - protected array $comparisonOperators = [ + protected array $comparisonOperatorMap = [ '!=s' => 'NOT IN', '=s' => 'IN', '!=' => '<>', '!*' => 'NOT ILIKE', '*' => 'ILIKE', - '>=' => '>=', - '<=' => '<=', - '>' => '>', - '<' => '<', - '=' => '=', ]; /** @var array */