From fd4d5a78cb0bd787fa46e4b7b2a6e3ffdb036dbd Mon Sep 17 00:00:00 2001 From: Miguel Muscat Date: Wed, 10 Jul 2024 10:17:11 +0200 Subject: [PATCH] Add EXISTS and NOT EXISTS to SELECT queries --- src/Expression/CallbackExpr.php | 25 +++++++++++++++++++++++++ src/Query/SelectQuery.php | 16 ++++++++++++++++ tests/Expression/CallbackExprTest.php | 26 ++++++++++++++++++++++++++ tests/Query/SelectQueryTest.php | 21 +++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 src/Expression/CallbackExpr.php create mode 100644 tests/Expression/CallbackExprTest.php diff --git a/src/Expression/CallbackExpr.php b/src/Expression/CallbackExpr.php new file mode 100644 index 0000000..d8439c9 --- /dev/null +++ b/src/Expression/CallbackExpr.php @@ -0,0 +1,25 @@ +callback = $callback; + } + + /** @inheritdoc */ + protected function toBaseString(): string + { + return call_user_func($this->callback); + } +} diff --git a/src/Query/SelectQuery.php b/src/Query/SelectQuery.php index 300b4cf..4089e4b 100644 --- a/src/Query/SelectQuery.php +++ b/src/Query/SelectQuery.php @@ -5,8 +5,10 @@ use RebelCode\Atlas\DatabaseAdapter; use RebelCode\Atlas\DataSource; use RebelCode\Atlas\Exception\QuerySqlException; +use RebelCode\Atlas\Expression\CallbackExpr; use RebelCode\Atlas\Expression\ColumnTerm; use RebelCode\Atlas\Expression\ExprInterface; +use RebelCode\Atlas\Expression\FnExpr; use RebelCode\Atlas\Expression\Term; use RebelCode\Atlas\Order; use RebelCode\Atlas\Query; @@ -128,6 +130,20 @@ public function getAlias(): ?string return $this->alias; } + public function exists(): ExprInterface + { + return new FnExpr('EXISTS', [ + new CallbackExpr(fn () => $this->toSql()), + ]); + } + + public function notExists(): ExprInterface + { + return new FnExpr('NOT EXISTS', [ + new CallbackExpr(fn () => $this->toSql()), + ]); + } + /** @inheritDoc */ public function toSql(): string { diff --git a/tests/Expression/CallbackExprTest.php b/tests/Expression/CallbackExprTest.php new file mode 100644 index 0000000..a928a9b --- /dev/null +++ b/tests/Expression/CallbackExprTest.php @@ -0,0 +1,26 @@ +assertEquals('foobar', $closure->toSql()); + } + + public function testRenderArrowFn() + { + $var = 'foobar'; + $closure = new CallbackExpr(fn () => $var); + + $this->assertEquals('foobar', $closure->toSql()); + } +} diff --git a/tests/Query/SelectQueryTest.php b/tests/Query/SelectQueryTest.php index 27be32b..721c8b6 100644 --- a/tests/Query/SelectQueryTest.php +++ b/tests/Query/SelectQueryTest.php @@ -14,6 +14,9 @@ use RebelCode\Atlas\Query\SelectQuery; use RebelCode\Atlas\Test\Helpers\ReflectionHelper; +use function RebelCode\Atlas\col; +use function RebelCode\Atlas\table; + class SelectQueryTest extends TestCase { use ReflectionHelper; @@ -446,4 +449,22 @@ public function testCompileSelectEverything() $this->assertEquals($expected, $actual); } + + public function testExists() + { + $query = new SelectQuery(); + $query = $query->from(table('test'))->where(col('role')->eq('admin')); + $exists = $query->exists(); + + $this->assertEquals("EXISTS(SELECT * FROM `test` WHERE (`role` = 'admin'))", $exists->toSql()); + } + + public function testNotExists() + { + $query = new SelectQuery(); + $query = $query->from(table('test'))->where(col('role')->eq('admin')); + $exists = $query->notExists(); + + $this->assertEquals("NOT EXISTS(SELECT * FROM `test` WHERE (`role` = 'admin'))", $exists->toSql()); + } }