Skip to content

Commit

Permalink
Implements QueryExpression::exists and QueryExpression::notExists met…
Browse files Browse the repository at this point in the history
…hods
  • Loading branch information
skie committed Jul 27, 2016
1 parent 1467f79 commit ebeeb73
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
22 changes: 22 additions & 0 deletions src/Database/Expression/QueryExpression.php
Expand Up @@ -372,6 +372,28 @@ public function notIn($field, $values, $type = null)
return $this->add(new Comparison($field, $values, $type, 'NOT IN'));
}

/**
* Adds a new condition to the expression object in the form "EXISTS (...)".
*
* @param \Cake\Database\ExpressionInterface $query the inner query
* @return $this
*/
public function exists(ExpressionInterface $query)
{
return $this->add(new UnaryExpression('EXISTS', $query, UnaryExpression::PREFIX));
}

/**
* Adds a new condition to the expression object in the form "NOT EXISTS (...)".
*
* @param \Cake\Database\ExpressionInterface $query the inner query
* @return $this
*/
public function notExists(ExpressionInterface $query)
{
return $this->add(new UnaryExpression('NOT EXISTS', $query, UnaryExpression::PREFIX));
}

/**
* Adds a new condition to the expression object in the form
* "field BETWEEN from AND to".
Expand Down
48 changes: 47 additions & 1 deletion tests/TestCase/Database/QueryTest.php
Expand Up @@ -1046,7 +1046,7 @@ public function testSelectWhereUsingExpressionInField()
*/
public function testSelectWhereOperatorMethods()
{
$this->loadFixtures('Articles', 'Comments');
$this->loadFixtures('Articles', 'Comments', 'Authors');
$query = new Query($this->connection);
$result = $query
->select(['title'])
Expand Down Expand Up @@ -2265,6 +2265,52 @@ public function testSubqueryInWhere()
$result->closeCursor();
}

/**
* Tests that Query objects can be included inside the where clause
* and be used as a EXISTS and NOT EXISTS conditions
*
* @return void
*/
public function testSubqueryExistsWhere()
{
$this->loadFixtures('Articles', 'Authors');
$query = new Query($this->connection);
$subQuery = (new Query($this->connection))
->select(['id'])
->from('articles')
->where(function ($exp) {
return $exp->equalFields('authors.id', 'articles.author_id');
});
$result = $query
->select(['id'])
->from('authors')
->where(function ($exp) use ($subQuery) {
return $exp->exists($subQuery);
})
->execute();
$this->assertCount(2, $result);
$this->assertEquals(['id' => 1], $result->fetch('assoc'));
$this->assertEquals(['id' => 3], $result->fetch('assoc'));

$query = new Query($this->connection);
$subQuery = (new Query($this->connection))
->select(['id'])
->from('articles')
->where(function ($exp) {
return $exp->equalFields('authors.id', 'articles.author_id');
});
$result = $query
->select(['id'])
->from('authors')
->where(function ($exp) use ($subQuery) {
return $exp->notExists($subQuery);
})
->execute();
$this->assertCount(2, $result);
$this->assertEquals(['id' => 2], $result->fetch('assoc'));
$this->assertEquals(['id' => 4], $result->fetch('assoc'));
}

/**
* Tests that it is possible to use a subquery in a join clause
*
Expand Down

0 comments on commit ebeeb73

Please sign in to comment.