From a0206f66fcb3456484acefc7964e94199521d0c3 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Tue, 1 Jan 2013 18:55:21 +0100 Subject: [PATCH] implementing and_ and or_ in QueryExpression --- .../Database/Expression/QueryExpression.php | 14 ++++ .../Model/Datasource/Database/QueryTest.php | 73 +++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/lib/Cake/Model/Datasource/Database/Expression/QueryExpression.php b/lib/Cake/Model/Datasource/Database/Expression/QueryExpression.php index 0eae916ef51..ac6c2741978 100644 --- a/lib/Cake/Model/Datasource/Database/Expression/QueryExpression.php +++ b/lib/Cake/Model/Datasource/Database/Expression/QueryExpression.php @@ -98,6 +98,20 @@ public function notIn($field, $values, $type = null) { return $this->add([$field . ' NOT IN' => $values], $type ? [$field => $type] : []); } + public function and_($conditions, $types = []) { + if (is_callable($conditions)) { + return $conditions(new self); + } + return new self($conditions, $types); + } + + public function or_($conditions, $types = []) { + if (is_callable($conditions)) { + return $conditions(new self([], [], 'OR')); + } + return new self($conditions, $types, 'OR'); + } + /** * Associates a query placeholder to a value and a type for next execution * diff --git a/lib/Cake/Test/TestCase/Model/Datasource/Database/QueryTest.php b/lib/Cake/Test/TestCase/Model/Datasource/Database/QueryTest.php index b618fba46d7..e9cd9f96464 100644 --- a/lib/Cake/Test/TestCase/Model/Datasource/Database/QueryTest.php +++ b/lib/Cake/Test/TestCase/Model/Datasource/Database/QueryTest.php @@ -735,4 +735,77 @@ public function testSelectWhereOperatorMethods() { $this->assertEquals(['id' => 3], $result->fetch('assoc')); } +/** + * Tests nesting query expressions both using arrays and closures + * + * @return void + **/ + public function testSelectExpressionComposition() { + $this->_insertDateRecords(); + $query = new Query($this->connection); + $result = $query + ->select(['id']) + ->from('dates') + ->where(function($exp) { + $and = $exp->and_(['id' => 2, 'id >' => 1]); + return $exp->add($and); + }) + ->execute(); + $this->assertCount(1, $result); + $this->assertEquals(['id' => 2], $result->fetch('assoc')); + + $query = new Query($this->connection); + $result = $query + ->select(['id']) + ->from('dates') + ->where(function($exp) { + $and = $exp->and_(['id' => 2, 'id <' => 2]); + return $exp->add($and); + }) + ->execute(); + $this->assertCount(0, $result); + + $query = new Query($this->connection); + $result = $query + ->select(['id']) + ->from('dates') + ->where(function($exp) { + $and = $exp->and_(function($and) { + return $and->eq('id', 1)->gt('id', 0); + }); + return $exp->add($and); + }) + ->execute(); + $this->assertCount(1, $result); + $this->assertEquals(['id' => 1], $result->fetch('assoc')); + + $query = new Query($this->connection); + $result = $query + ->select(['id']) + ->from('dates') + ->where(function($exp) { + $or = $exp->or_(['id' => 1]); + $and = $exp->and_(['id >' => 2, 'id <' => 4]); + return $or->add($and); + }) + ->execute(); + $this->assertCount(2, $result); + $this->assertEquals(['id' => 1], $result->fetch('assoc')); + $this->assertEquals(['id' => 3], $result->fetch('assoc')); + + $query = new Query($this->connection); + $result = $query + ->select(['id']) + ->from('dates') + ->where(function($exp) { + $or = $exp->or_(function($or) { + return $or->eq('id', 1)->eq('id', 2); + }); + return $or; + }) + ->execute(); + $this->assertCount(2, $result); + $this->assertEquals(['id' => 1], $result->fetch('assoc')); + $this->assertEquals(['id' => 2], $result->fetch('assoc')); + } }