Skip to content

Commit

Permalink
Merge pull request #3696 from bingo-soft/master
Browse files Browse the repository at this point in the history
Add support for DISTINCT clause
  • Loading branch information
morozov authored Oct 13, 2019
2 parents 81922a2 + f90c299 commit 7241a65
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 14 deletions.
15 changes: 15 additions & 0 deletions docs/en/reference/query-builder.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ and ``delete($tableName)``:
You can convert a query builder to its SQL string representation
by calling ``$queryBuilder->getSQL()`` or casting the object to string.

DISTINCT-Clause
~~~~~~~~~~~~~~~

The ``SELECT`` statement can be specified with a ``DISTINCT`` clause:

.. code-block:: php
<?php
$queryBuilder
->select('name')
->distinct()
->from('users')
;
WHERE-Clause
~~~~~~~~~~~~

Expand Down
53 changes: 39 additions & 14 deletions lib/Doctrine/DBAL/Query/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,28 @@ class QueryBuilder
*/
private $connection;

/*
* The default values of SQL parts collection
*/
private const SQL_PARTS_DEFAULTS = [
'select' => [],
'distinct' => false,
'from' => [],
'join' => [],
'set' => [],
'where' => null,
'groupBy' => [],
'having' => null,
'orderBy' => [],
'values' => [],
];

/**
* The array of SQL parts collected.
*
* @var mixed[]
*/
private $sqlParts = [
'select' => [],
'from' => [],
'join' => [],
'set' => [],
'where' => null,
'groupBy' => [],
'having' => null,
'orderBy' => [],
'values' => [],
];
private $sqlParts = self::SQL_PARTS_DEFAULTS;

/**
* The complete SQL string for this query.
Expand Down Expand Up @@ -469,6 +475,25 @@ public function select($select = null)
return $this->add('select', $selects);
}

/**
* Adds DISTINCT to the query.
*
* <code>
* $qb = $conn->createQueryBuilder()
* ->select('u.id')
* ->distinct()
* ->from('users', 'u')
* </code>
*
* @return $this This QueryBuilder instance.
*/
public function distinct() : self
{
$this->sqlParts['distinct'] = true;

return $this;
}

/**
* Adds an item that is to be returned in the query result.
*
Expand Down Expand Up @@ -1083,8 +1108,7 @@ public function resetQueryParts($queryPartNames = null)
*/
public function resetQueryPart($queryPartName)
{
$this->sqlParts[$queryPartName] = is_array($this->sqlParts[$queryPartName])
? [] : null;
$this->sqlParts[$queryPartName] = self::SQL_PARTS_DEFAULTS[$queryPartName];

$this->state = self::STATE_DIRTY;

Expand All @@ -1098,7 +1122,8 @@ public function resetQueryPart($queryPartName)
*/
private function getSQLForSelect()
{
$query = 'SELECT ' . implode(', ', $this->sqlParts['select']);
$query = 'SELECT ' . ($this->sqlParts['distinct'] ? 'DISTINCT ' : '') .
implode(', ', $this->sqlParts['select']);

$query .= ($this->sqlParts['from'] ? ' FROM ' . implode(', ', $this->getFromClauses()) : '')
. ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '')
Expand Down
11 changes: 11 additions & 0 deletions tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ public function testSimpleSelect() : void
self::assertEquals('SELECT u.id FROM users u', (string) $qb);
}

public function testSimpleSelectWithDistinct() : void
{
$qb = new QueryBuilder($this->conn);

$qb->select('u.id')
->distinct()
->from('users', 'u');

self::assertEquals('SELECT DISTINCT u.id FROM users u', (string) $qb);
}

public function testSelectWithSimpleWhere() : void
{
$qb = new QueryBuilder($this->conn);
Expand Down

0 comments on commit 7241a65

Please sign in to comment.