From 369f3ba9a50cc19d461c7f1e2ab658a5a5a57788 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Tue, 7 Mar 2023 18:52:49 +0200 Subject: [PATCH] switch complex expr --- .../Espo/ORM/Query/Part/Expression.php | 15 ++++++++++ .../ORM/QueryComposer/BaseQueryComposer.php | 22 +++++++++++++++ .../Espo/ORM/QueryComposer/Functions.php | 1 + .../unit/Espo/ORM/MysqlQueryComposerTest.php | 28 +++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/application/Espo/ORM/Query/Part/Expression.php b/application/Espo/ORM/Query/Part/Expression.php index 3badfb7a9f..37a01596d1 100644 --- a/application/Espo/ORM/Query/Part/Expression.php +++ b/application/Espo/ORM/Query/Part/Expression.php @@ -186,6 +186,21 @@ class Expression implements WhereItem return self::composeFunction('IF', $condition, $then, $else); } + /** + * 'CASE' expression. Even arguments define 'WHEN' conditions, following odd arguments + * define 'THEN' values. The last unmatched argument defines 'ELSE'. + * + * @param Expression|scalar|null ...$arguments Arguments. + */ + public static function switch(Expression|string|int|float|bool|null ...$arguments): self + { + if (count($arguments) < 2) { + throw new RuntimeException("Too few arguments."); + } + + return self::composeFunction('SWITCH', ...$arguments); + } + /** * 'IFNULL' function. If the first argument is not NULL, returns it, * otherwise returns the second argument. diff --git a/application/Espo/ORM/QueryComposer/BaseQueryComposer.php b/application/Espo/ORM/QueryComposer/BaseQueryComposer.php index 63f4d79cf9..6dc95b66e7 100644 --- a/application/Espo/ORM/QueryComposer/BaseQueryComposer.php +++ b/application/Espo/ORM/QueryComposer/BaseQueryComposer.php @@ -950,6 +950,28 @@ abstract class BaseQueryComposer implements QueryComposer } switch ($function) { + case 'SWITCH': + if (count($argumentPartList) < 2) { + throw new RuntimeException("Not enough arguments for SWITCH function."); + } + + $part = "CASE"; + + for ($i = 0; $i < floor(count($argumentPartList) / 2); $i++) { + $whenPart = $argumentPartList[$i * 2]; + $thenPart = $argumentPartList[$i * 2 + 1]; + + $part .= " WHEN {$whenPart} THEN {$thenPart}"; + } + + if (count($argumentPartList) % 2) { + $part .= " ELSE " . end($argumentPartList); + } + + $part .= " END"; + + return $part; + case 'MONTH': return "DATE_FORMAT({$part}, '%Y-%m')"; diff --git a/application/Espo/ORM/QueryComposer/Functions.php b/application/Espo/ORM/QueryComposer/Functions.php index b479ad961c..e8ef5dd954 100644 --- a/application/Espo/ORM/QueryComposer/Functions.php +++ b/application/Espo/ORM/QueryComposer/Functions.php @@ -122,6 +122,7 @@ class Functions 'NOT_IN', 'IFNULL', 'NULLIF', + 'SWITCH', 'BINARY', 'MD5', 'UNIX_TIMESTAMP', diff --git a/tests/unit/Espo/ORM/MysqlQueryComposerTest.php b/tests/unit/Espo/ORM/MysqlQueryComposerTest.php index d01502a3f0..c52c844b1c 100644 --- a/tests/unit/Espo/ORM/MysqlQueryComposerTest.php +++ b/tests/unit/Espo/ORM/MysqlQueryComposerTest.php @@ -2888,4 +2888,32 @@ class MysqlQueryComposerTest extends \PHPUnit\Framework\TestCase $this->query->composeSelect($query) ); } + + public function testSwitch1(): void + { + $sql = "SELECT CASE WHEN 1 THEN '1' WHEN 0 THEN '0' ELSE NULL END AS `value`"; + + $query = SelectBuilder::create() + ->select('SWITCH:(1, "1", 0, "0", null)', 'value') + ->build(); + + $this->assertEquals( + $sql, + $this->query->composeSelect($query) + ); + } + + public function testSwitch2(): void + { + $sql = "SELECT CASE WHEN 1 THEN '1' WHEN 0 THEN '0' END AS `value`"; + + $query = SelectBuilder::create() + ->select('SWITCH:(1, "1", 0, "0")', 'value') + ->build(); + + $this->assertEquals( + $sql, + $this->query->composeSelect($query) + ); + } }