Skip to content

Commit 7241a65

Browse files
authored
Merge pull request #3696 from bingo-soft/master
Add support for DISTINCT clause
2 parents 81922a2 + f90c299 commit 7241a65

File tree

3 files changed

+65
-14
lines changed

3 files changed

+65
-14
lines changed

docs/en/reference/query-builder.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ and ``delete($tableName)``:
8787
You can convert a query builder to its SQL string representation
8888
by calling ``$queryBuilder->getSQL()`` or casting the object to string.
8989

90+
DISTINCT-Clause
91+
~~~~~~~~~~~~~~~
92+
93+
The ``SELECT`` statement can be specified with a ``DISTINCT`` clause:
94+
95+
.. code-block:: php
96+
97+
<?php
98+
99+
$queryBuilder
100+
->select('name')
101+
->distinct()
102+
->from('users')
103+
;
104+
90105
WHERE-Clause
91106
~~~~~~~~~~~~
92107

lib/Doctrine/DBAL/Query/QueryBuilder.php

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,28 @@ class QueryBuilder
5252
*/
5353
private $connection;
5454

55+
/*
56+
* The default values of SQL parts collection
57+
*/
58+
private const SQL_PARTS_DEFAULTS = [
59+
'select' => [],
60+
'distinct' => false,
61+
'from' => [],
62+
'join' => [],
63+
'set' => [],
64+
'where' => null,
65+
'groupBy' => [],
66+
'having' => null,
67+
'orderBy' => [],
68+
'values' => [],
69+
];
70+
5571
/**
5672
* The array of SQL parts collected.
5773
*
5874
* @var mixed[]
5975
*/
60-
private $sqlParts = [
61-
'select' => [],
62-
'from' => [],
63-
'join' => [],
64-
'set' => [],
65-
'where' => null,
66-
'groupBy' => [],
67-
'having' => null,
68-
'orderBy' => [],
69-
'values' => [],
70-
];
76+
private $sqlParts = self::SQL_PARTS_DEFAULTS;
7177

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

478+
/**
479+
* Adds DISTINCT to the query.
480+
*
481+
* <code>
482+
* $qb = $conn->createQueryBuilder()
483+
* ->select('u.id')
484+
* ->distinct()
485+
* ->from('users', 'u')
486+
* </code>
487+
*
488+
* @return $this This QueryBuilder instance.
489+
*/
490+
public function distinct() : self
491+
{
492+
$this->sqlParts['distinct'] = true;
493+
494+
return $this;
495+
}
496+
472497
/**
473498
* Adds an item that is to be returned in the query result.
474499
*
@@ -1083,8 +1108,7 @@ public function resetQueryParts($queryPartNames = null)
10831108
*/
10841109
public function resetQueryPart($queryPartName)
10851110
{
1086-
$this->sqlParts[$queryPartName] = is_array($this->sqlParts[$queryPartName])
1087-
? [] : null;
1111+
$this->sqlParts[$queryPartName] = self::SQL_PARTS_DEFAULTS[$queryPartName];
10881112

10891113
$this->state = self::STATE_DIRTY;
10901114

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

11031128
$query .= ($this->sqlParts['from'] ? ' FROM ' . implode(', ', $this->getFromClauses()) : '')
11041129
. ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '')

tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ public function testSimpleSelect() : void
5050
self::assertEquals('SELECT u.id FROM users u', (string) $qb);
5151
}
5252

53+
public function testSimpleSelectWithDistinct() : void
54+
{
55+
$qb = new QueryBuilder($this->conn);
56+
57+
$qb->select('u.id')
58+
->distinct()
59+
->from('users', 'u');
60+
61+
self::assertEquals('SELECT DISTINCT u.id FROM users u', (string) $qb);
62+
}
63+
5364
public function testSelectWithSimpleWhere() : void
5465
{
5566
$qb = new QueryBuilder($this->conn);

0 commit comments

Comments
 (0)