Skip to content
28 changes: 28 additions & 0 deletions docs/en/reference/query-builder.rst
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,34 @@ Multiple CTEs can be defined by calling the with method multiple times.

Values of parameters used in a CTE should be defined in the main QueryBuilder.

Comments
~~~~~~~~~~~
Comment thread
greg0ire marked this conversation as resolved.
Outdated

To add comments to the query you can use the ``withComment()`` method which will add the comment at the top of the query:
Comment thread
greg0ire marked this conversation as resolved.
Outdated

.. code-block:: php

<?php

$queryBuilder
->select('id', 'name')
->from('users')
->withComment('This is a comment');
// /* This is a comment */ SELECT id, name FROM users

Multiple comments can be added by calling the method multiple times:

.. code-block:: php

<?php

$queryBuilder
->select('id', 'name')
->from('users')
->withComment('Comment 1')
->withComment('Comment 2');
// /* Comment 1 */ /* Comment 2 */ SELECT id, name FROM users

Building Expressions
--------------------

Expand Down
28 changes: 27 additions & 1 deletion src/Query/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ class QueryBuilder
*/
private array $commonTableExpressions = [];

/**
* Comments that will be added to the query.
*
* @var string[]
*/
private array $comments = [];

/**
* The query cache profile used for caching results.
*/
Expand Down Expand Up @@ -358,7 +365,7 @@ public function executeStatement(): int|string
*/
public function getSQL(): string
{
return $this->sql ??= match ($this->type) {
return $this->sql ??= $this->getComments() . match ($this->type) {
QueryType::INSERT => $this->getSQLForInsert(),
QueryType::DELETE => $this->getSQLForDelete(),
QueryType::UPDATE => $this->getSQLForUpdate(),
Expand Down Expand Up @@ -1625,4 +1632,23 @@ public function disableResultCache(): self

return $this;
}

public function withComment(string $comment): self
Comment thread
greg0ire marked this conversation as resolved.
Outdated
{
$this->comments[] = $comment;

$this->sql = null;

return $this;
}

private function getComments(): string
{
$comments = '';
foreach ($this->comments as $comment) {
$comments .= sprintf('/* %s */ ', $comment);
}

return $comments;
}
}
16 changes: 16 additions & 0 deletions tests/Functional/Query/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,22 @@ public function testSelectWithCTEUnion(): void
self::assertSame($expectedRows, $qb->executeQuery()->fetchAllAssociative());
}

public function testSelectWithComment(): void
{
$expectedRows = $this->prepareExpectedRows([['id' => 1], ['id' => 2]]);
$qb = $this->connection->createQueryBuilder();

$select = $qb
->select('id')
->from('for_update')
->where('id IN (?, ?)')
->setParameters([1, 2], [ParameterType::INTEGER, ParameterType::INTEGER])
->withComment('Test comment');

self::assertSame('/* Test comment */ SELECT id FROM for_update WHERE id IN (?, ?)', $select->getSQL());
self::assertSame($expectedRows, $select->executeQuery()->fetchAllAssociative());
}

public function testPlatformDoesNotSupportCTE(): void
{
if ($this->platformSupportsCTEs()) {
Expand Down
45 changes: 45 additions & 0 deletions tests/Query/QueryBuilderTest.php
Comment thread
greg0ire marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ public function testSimpleSelectWithoutFrom(): void
self::assertEquals('SELECT some_function()', (string) $qb);
}

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

$qb->select('some_function()')
->withComment('Test comment');

self::assertEquals('/* Test comment */ SELECT some_function()', (string) $qb);
}

public function testSimpleSelect(): void
{
$qb = new QueryBuilder($this->conn);
Expand Down Expand Up @@ -414,6 +424,17 @@ public function testUpdate(): void
self::assertEquals('UPDATE users SET foo = ?, bar = ?', (string) $qb);
}

public function testUpdateWithComment(): void
{
$qb = new QueryBuilder($this->conn);
$qb->update('users')
->set('foo', '?')
->set('bar', '?')
->withComment('Test comment');

self::assertEquals('/* Test comment */ UPDATE users SET foo = ?, bar = ?', (string) $qb);
}

public function testUpdateWhere(): void
{
$qb = new QueryBuilder($this->conn);
Expand All @@ -432,6 +453,15 @@ public function testDelete(): void
self::assertEquals('DELETE FROM users', (string) $qb);
}

public function testDeleteWithComment(): void
{
$qb = new QueryBuilder($this->conn);
$qb->delete('users');
$qb->withComment('Test comment');

self::assertEquals('/* Test comment */ DELETE FROM users', (string) $qb);
}

public function testDeleteWhere(): void
{
$qb = new QueryBuilder($this->conn);
Expand All @@ -455,6 +485,21 @@ public function testInsertValues(): void
self::assertEquals('INSERT INTO users (foo, bar) VALUES(?, ?)', (string) $qb);
}

public function testInsertValuesWithComment(): void
{
$qb = new QueryBuilder($this->conn);
$qb->insert('users')
->values(
[
'foo' => '?',
'bar' => '?',
],
)
->withComment('Test comment');

self::assertEquals('/* Test comment */ INSERT INTO users (foo, bar) VALUES(?, ?)', (string) $qb);
}

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