From 6eb29eef2b16d45a1bb492714910550ea332608f Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Sun, 13 Nov 2022 11:05:42 +0200 Subject: [PATCH] orm join support expression on the left --- .../ORM/QueryComposer/BaseQueryComposer.php | 35 ++++++++++++------- .../unit/Espo/ORM/MysqlQueryComposerTest.php | 27 ++++++++++++-- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/application/Espo/ORM/QueryComposer/BaseQueryComposer.php b/application/Espo/ORM/QueryComposer/BaseQueryComposer.php index b203ad378a..aa51b72138 100644 --- a/application/Espo/ORM/QueryComposer/BaseQueryComposer.php +++ b/application/Espo/ORM/QueryComposer/BaseQueryComposer.php @@ -2578,7 +2578,7 @@ abstract class BaseQueryComposer implements QueryComposer $leftPart = null; - if (substr($field, -1) === ':') { + if (str_ends_with($field, ':')) { $field = substr($field, 0, strlen($field) - 1); $isNotValue = true; @@ -2586,7 +2586,7 @@ abstract class BaseQueryComposer implements QueryComposer if (!preg_match('/^[a-z0-9]+$/i', $field)) { foreach ($this->comparisonOperators as $op => $opDb) { - if (substr($field, -strlen($op)) === $op) { + if (str_ends_with($field, $op)) { $field = trim(substr($field, 0, -strlen($op))); $operatorOrm = $op; @@ -3043,15 +3043,16 @@ abstract class BaseQueryComposer implements QueryComposer $operator = '='; $isNotValue = false; + $isComplex = false; - if (substr($left, -1) === ':') { + if (str_ends_with($left, ':')) { $left = substr($left, 0, strlen($left) - 1); $isNotValue = true; } if (!preg_match('/^[a-z0-9]+$/i', $left)) { foreach ($this->comparisonOperators as $op => $opDb) { - if (substr($left, -strlen($op)) === $op) { + if (str_ends_with($left, $op)) { $left = trim(substr($left, 0, -strlen($op))); $operator = $opDb; @@ -3060,17 +3061,27 @@ abstract class BaseQueryComposer implements QueryComposer } } - if (strpos($left, '.') > 0) { - list($alias, $attribute) = explode('.', $left); + if (Util::isComplexExpression($left)) { + $stub = []; - $alias = $this->sanitize($alias); - $column = $this->toDb($this->sanitize($attribute)); - } - else { - $column = $this->toDb($this->sanitize($left)); + $sql .= $this->convertComplexExpression($entity, $left, false, $stub); + + $isComplex = true; } - $sql .= "{$alias}.{$column}"; + if (!$isComplex) { + if (strpos($left, '.') > 0) { + list($alias, $attribute) = explode('.', $left); + + $alias = $this->sanitize($alias); + $column = $this->toDb($this->sanitize($attribute)); + } + else { + $column = $this->toDb($this->sanitize($left)); + } + + $sql .= "{$alias}.{$column}"; + } if (is_array($right)) { $arr = []; diff --git a/tests/unit/Espo/ORM/MysqlQueryComposerTest.php b/tests/unit/Espo/ORM/MysqlQueryComposerTest.php index 9a0402e803..b30e5acfab 100644 --- a/tests/unit/Espo/ORM/MysqlQueryComposerTest.php +++ b/tests/unit/Espo/ORM/MysqlQueryComposerTest.php @@ -44,12 +44,12 @@ use Espo\ORM\{ }; use Espo\ORM\Query\{ + Part\Condition, Select, Insert, Update, Delete, - LockTableBuilder, -}; + LockTableBuilder}; use RuntimeException; @@ -832,6 +832,29 @@ class MysqlQueryComposerTest extends \PHPUnit\Framework\TestCase $this->assertEquals($expectedSql, $sql); } + public function testJoinConditions5(): void + { + $query = $this->queryBuilder + ->select('id') + ->from('Note') + ->leftJoin( + 'Post', + 'post', + Condition::notEqual( + Expression::value('TEST'), + Expression::column('post.id') + ) + ) + ->withDeleted() + ->build(); + + $sql = $this->query->composeSelect($query); + + $expectedSql = "SELECT note.id AS `id` FROM `note` LEFT JOIN `post` AS `post` ON 'TEST' <> post.id"; + + $this->assertEquals($expectedSql, $sql); + } + public function testJoinTable1() { $sql = $this->query->compose(Select::fromRaw([