Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
~~~~~~~~~~~

To add comments to the query you can use the ``withComment()`` method which will add the comment at the top of the query:

.. 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
{
$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
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