Skip to content
Merged
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
8 changes: 8 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ Using `Doctrine\ORM\QueryBuilder::add('join', ...)` with a list of join parts
is deprecated in favor of using an associative array of join parts with the
root alias as key.

## Deprecate using the `WITH` keyword for arbitrary DQL joins

Using the `WITH` keyword to specify the condition for an arbitrary DQL join is
deprecated in favor of using the `ON` keyword (similar to the SQL syntax for
joins).
The `WITH` keyword is now meant to be used only for filtering conditions in
association joins.

# Upgrade to 3.5

See the General notes to upgrading to 3.x versions above.
Expand Down
19 changes: 13 additions & 6 deletions docs/en/reference/dql-doctrine-query-language.rst
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ where you can generate an arbitrary join with the following syntax:
.. code-block:: php

<?php
$query = $em->createQuery('SELECT u FROM User u JOIN Banlist b WITH u.email = b.email');
$query = $em->createQuery('SELECT u FROM User u JOIN Banlist b ON u.email = b.email');

With an arbitrary join the result differs from the joins using a mapped property.
The result of an arbitrary join is an one dimensional array with a mix of the entity from the ``SELECT``
Expand All @@ -513,13 +513,15 @@ it loads all the related ``Banlist`` objects corresponding to this ``User``. Thi
when the DQL is switched to an arbitrary join.

.. note::
The differences between WHERE, WITH and HAVING clauses may be
The differences between WHERE, WITH, ON and HAVING clauses may be
confusing.

- WHERE is applied to the results of an entire query
- WITH is applied to a join as an additional condition. For
arbitrary joins (SELECT f, b FROM Foo f, Bar b WITH f.id = b.id)
the WITH is required, even if it is 1 = 1
- ON is applied to arbitrary joins as the join condition. For
arbitrary joins (SELECT f, b FROM Foo f, Bar b ON f.id = b.id)
the ON is required, even if it is 1 = 1. WITH is also
supported as alternative keyword for that case for BC reasons.
- WITH is applied to an association join as an additional condition.
- HAVING is applied to the results of a query after
aggregation (GROUP BY)

Expand Down Expand Up @@ -1699,9 +1701,14 @@ From, Join and Index by
SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration
RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable
JoinAssociationDeclaration ::= JoinAssociationPathExpression ["AS"] AliasIdentificationVariable [IndexBy]
Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" (JoinAssociationDeclaration | RangeVariableDeclaration) ["WITH" ConditionalExpression]
Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" (JoinAssociationDeclaration ["WITH" ConditionalExpression] | RangeVariableDeclaration [("ON" | "WITH") ConditionalExpression])
IndexBy ::= "INDEX" "BY" SingleValuedPathExpression

.. note::
Using the ``WITH`` keyword for the ``ConditionalExpression`` of a
``RangeVariableDeclaration`` is deprecated and will be removed in
ORM 4.0. Use the ``ON`` keyword instead.

Select Expressions
~~~~~~~~~~~~~~~~~~

Expand Down
35 changes: 22 additions & 13 deletions src/Query/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -1609,8 +1609,7 @@ public function SubselectIdentificationVariableDeclaration(): AST\Identification

/**
* Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN"
* (JoinAssociationDeclaration | RangeVariableDeclaration)
* ["WITH" ConditionalExpression]
* (JoinAssociationDeclaration ["WITH" ConditionalExpression] | RangeVariableDeclaration [("ON" | "WITH") ConditionalExpression])
*/
public function Join(): AST\Join
{
Expand Down Expand Up @@ -1644,22 +1643,32 @@ public function Join(): AST\Join

$next = $this->lexer->glimpse();
assert($next !== null);
$joinDeclaration = $next->type === TokenType::T_DOT ? $this->JoinAssociationDeclaration() : $this->RangeVariableDeclaration();
$adhocConditions = $this->lexer->isNextToken(TokenType::T_WITH);
$join = new AST\Join($joinType, $joinDeclaration);
$conditionalExpression = null;

// Describe non-root join declaration
if ($joinDeclaration instanceof AST\RangeVariableDeclaration) {
$joinDeclaration->isRoot = false;
}
if ($next->type === TokenType::T_DOT) {
$joinDeclaration = $this->JoinAssociationDeclaration();

// Check for ad-hoc Join conditions
if ($adhocConditions) {
$this->match(TokenType::T_WITH);
if ($this->lexer->isNextToken(TokenType::T_WITH)) {
$this->match(TokenType::T_WITH);
$conditionalExpression = $this->ConditionalExpression();
}
} else {
$joinDeclaration = $this->RangeVariableDeclaration();
$joinDeclaration->isRoot = false;

$join->conditionalExpression = $this->ConditionalExpression();
if ($this->lexer->isNextToken(TokenType::T_ON)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a computer near me right now, so I cannot try out... But what happens when you omit the ˋWITHˋ as well as ˋONˋ here?

Is it possible to get away with a JOIN without a condition and should we prevent that from happening?

Copy link
Member Author

@stof stof Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was already supported before. The SqlWalker has code to deal with it (even though the doc says the join condition is required for arbitrary joins). Note that the query generated for a join without condition might have worse performance:

$isUnconditionalJoin = $conditions === [];

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And see this if ($adhocConditions) { in the old code that was making the WITH keyword optional.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, would it make sense to remove the

ON is required, even if it is 1 = 1

remark from the docs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will keep it for now, because I'm not sure this is something we should actually encourage, given the kind of hacks it requires for cross-platform support.
In my opinion, it might make sense to deprecate the case of an arbitrary join without a join condition. I guess the main reason it was initially supported is related to the fact that this was initially parsed on top of association joins (which is why it was implemented with the WITH keyword instead of the intended ON), where the filter condition is optional (because an association join already has a built-in condition for the association)

$this->match(TokenType::T_ON);
$conditionalExpression = $this->ConditionalExpression();
} elseif ($this->lexer->isNextToken(TokenType::T_WITH)) {
$this->match(TokenType::T_WITH);
$conditionalExpression = $this->ConditionalExpression();
Deprecation::trigger('doctrine/orm', 'https://github.com/doctrine/orm/issues/12192', 'Using WITH for the join condition of arbitrary joins is deprecated. Use ON instead.');
}
}

$join = new AST\Join($joinType, $joinDeclaration);
$join->conditionalExpression = $conditionalExpression;

return $join;
}

Expand Down
1 change: 1 addition & 0 deletions src/Query/TokenType.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,5 @@ enum TokenType: int
case T_WHERE = 255;
case T_WITH = 256;
case T_NAMED = 257;
case T_ON = 258;
}
6 changes: 3 additions & 3 deletions tests/Tests/ORM/Functional/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ public function testToIterableWithMultipleSelectElements(): void
$this->_em->flush();
$this->_em->clear();

$query = $this->_em->createQuery('select a, u from ' . CmsArticle::class . ' a JOIN ' . CmsUser::class . ' u WITH a.user = u');
$query = $this->_em->createQuery('select a, u from ' . CmsArticle::class . ' a JOIN ' . CmsUser::class . ' u ON a.user = u');

$result = iterator_to_array($query->toIterable());

Expand Down Expand Up @@ -1059,7 +1059,7 @@ public function testMultipleJoinComponentsUsingInnerJoin(): void
$query = $this->_em->createQuery('
SELECT u, p
FROM Doctrine\Tests\Models\CMS\CmsUser u
INNER JOIN Doctrine\Tests\Models\CMS\CmsPhonenumber p WITH u = p.user
INNER JOIN Doctrine\Tests\Models\CMS\CmsPhonenumber p ON u = p.user
');
$users = $query->execute();

Expand Down Expand Up @@ -1092,7 +1092,7 @@ public function testMultipleJoinComponentsUsingLeftJoin(): void
$query = $this->_em->createQuery('
SELECT u, p
FROM Doctrine\Tests\Models\CMS\CmsUser u
LEFT JOIN Doctrine\Tests\Models\CMS\CmsPhonenumber p WITH u = p.user
LEFT JOIN Doctrine\Tests\Models\CMS\CmsPhonenumber p ON u = p.user
');
$users = $query->execute();

Expand Down
2 changes: 1 addition & 1 deletion tests/Tests/ORM/Functional/Ticket/DDC3042Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function testSQLGenerationDoesNotProvokeAliasCollisions(): void
$this
->_em
->createQuery(
'SELECT f, b FROM ' . __NAMESPACE__ . '\DDC3042Foo f JOIN ' . __NAMESPACE__ . '\DDC3042Bar b WITH 1 = 1',
'SELECT f, b FROM ' . __NAMESPACE__ . '\DDC3042Foo f JOIN ' . __NAMESPACE__ . '\DDC3042Bar b ON 1 = 1',
)
->getSQL(),
'field_11',
Expand Down
2 changes: 1 addition & 1 deletion tests/Tests/ORM/Functional/Ticket/GH6362Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protected function setUp(): void
* SELECT a as base, b, c, d
* FROM Start a
* LEFT JOIN a.bases b
* LEFT JOIN Child c WITH b.id = c.id
* LEFT JOIN Child c ON b.id = c.id
* LEFT JOIN c.joins d
*/
#[Group('GH-6362')]
Expand Down
2 changes: 1 addition & 1 deletion tests/Tests/ORM/Functional/Ticket/GH6464Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function testIssue(): void
$query = $this->_em->createQueryBuilder()
->select('p')
->from(GH6464Post::class, 'p')
->innerJoin(GH6464Author::class, 'a', 'WITH', 'p.authorId = a.id')
->innerJoin(GH6464Author::class, 'a', 'ON', 'p.authorId = a.id')
->getQuery();

self::assertDoesNotMatchRegularExpression(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected function setUp(): void
public function testNonUniqueObjectHydrationDuringIteration(): void
{
$q = $this->_em->createQuery(
'SELECT b FROM ' . GH7496EntityAinB::class . ' aib JOIN ' . GH7496EntityB::class . ' b WITH aib.eB = b',
'SELECT b FROM ' . GH7496EntityAinB::class . ' aib JOIN ' . GH7496EntityB::class . ' b ON aib.eB = b',
);

$bs = IterableTester::iterableToArray(
Expand Down
13 changes: 12 additions & 1 deletion tests/Tests/ORM/Query/LanguageRecognitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Doctrine\Tests\ORM\Query;

use Doctrine\Deprecations\PHPUnit\VerifyDeprecations;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\Column;
Expand All @@ -20,9 +21,12 @@
use Doctrine\Tests\OrmTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\IgnoreDeprecations;

class LanguageRecognitionTest extends OrmTestCase
{
use VerifyDeprecations;

private EntityManagerInterface $entityManager;
private int $hydrationMode = AbstractQuery::HYDRATE_OBJECT;

Expand Down Expand Up @@ -262,8 +266,15 @@ public function testMixingOfJoins(): void
$this->assertValidDQL('SELECT u.name, a.topic, p.phonenumber FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.articles a LEFT JOIN u.phonenumbers p');
}

public function testJoinClassPathUsingON(): void
{
$this->assertValidDQL('SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN Doctrine\Tests\Models\CMS\CmsArticle a ON a.user = u.id');
}

#[IgnoreDeprecations]
public function testJoinClassPathUsingWITH(): void
{
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/12192');
$this->assertValidDQL('SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN Doctrine\Tests\Models\CMS\CmsArticle a WITH a.user = u.id');
}

Expand Down Expand Up @@ -638,7 +649,7 @@ public function testHavingSupportIsNullExpression(): void
#[Group('DDC-3085')]
public function testHavingSupportResultVariableInNullComparisonExpression(): void
{
$this->assertValidDQL('SELECT u AS user, SUM(a.id) AS score FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN Doctrine\Tests\Models\CMS\CmsAddress a WITH a.user = u GROUP BY u HAVING score IS NOT NULL AND score >= 5');
$this->assertValidDQL('SELECT u AS user, SUM(a.id) AS score FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN Doctrine\Tests\Models\CMS\CmsAddress a ON a.user = u GROUP BY u HAVING score IS NOT NULL AND score >= 5');
}

#[Group('DDC-1858')]
Expand Down
18 changes: 9 additions & 9 deletions tests/Tests/ORM/Query/SelectSqlGenerationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,25 +191,25 @@ public function testSupportsSelectUsingMultipleFromComponents(): void
public function testSupportsJoinOnMultipleComponents(): void
{
$this->assertSqlGeneration(
'SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN Doctrine\Tests\Models\CMS\CmsPhonenumber p WITH u = p.user',
'SELECT u, p FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN Doctrine\Tests\Models\CMS\CmsPhonenumber p ON u = p.user',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, c1_.phonenumber AS phonenumber_4, c0_.email_id AS email_id_5, c1_.user_id AS user_id_6 FROM cms_users c0_ INNER JOIN cms_phonenumbers c1_ ON (c0_.id = c1_.user_id)',
);
}

public function testSupportsJoinOnMultipleComponentsWithJoinedInheritanceType(): void
{
$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e JOIN Doctrine\Tests\Models\Company\CompanyManager m ON e.id = m.id',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c2_.car_id AS car_id_8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id INNER JOIN (company_managers c3_ INNER JOIN company_employees c5_ ON c3_.id = c5_.id INNER JOIN company_persons c4_ ON c3_.id = c4_.id) ON (c0_.id = c4_.id)',
);

$this->assertSqlGeneration(
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyManager m WITH e.id = m.id',
'SELECT e FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyManager m ON e.id = m.id',
'SELECT c0_.id AS id_0, c0_.name AS name_1, c1_.salary AS salary_2, c1_.department AS department_3, c1_.startDate AS startDate_4, c2_.title AS title_5, c0_.discr AS discr_6, c0_.spouse_id AS spouse_id_7, c2_.car_id AS car_id_8 FROM company_employees c1_ INNER JOIN company_persons c0_ ON c1_.id = c0_.id LEFT JOIN company_managers c2_ ON c1_.id = c2_.id LEFT JOIN (company_managers c3_ INNER JOIN company_employees c5_ ON c3_.id = c5_.id INNER JOIN company_persons c4_ ON c3_.id = c4_.id) ON (c0_.id = c4_.id)',
);

$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c JOIN c.salesPerson s LEFT JOIN Doctrine\Tests\Models\Company\CompanyEvent e WITH s.id = e.id',
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c JOIN c.salesPerson s LEFT JOIN Doctrine\Tests\Models\Company\CompanyEvent e ON s.id = e.id',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_contracts c0_ INNER JOIN company_employees c1_ ON c0_.salesPerson_id = c1_.id LEFT JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id LEFT JOIN (company_events c4_ LEFT JOIN company_auctions c5_ ON c4_.id = c5_.id LEFT JOIN company_raffles c6_ ON c4_.id = c6_.id) ON (c2_.id = c4_.id) WHERE c0_.discr IN ('fix', 'flexible', 'flexultra')",
);
}
Expand Down Expand Up @@ -2025,7 +2025,7 @@ public function testSingleTableInheritanceLeftJoinWithCondition(): void
{
// Regression test for the bug
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id',
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyContract c ON c.salesPerson = e.id',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id LEFT JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra')",
);
}
Expand All @@ -2035,7 +2035,7 @@ public function testSingleTableInheritanceLeftJoinWithConditionAndWhere(): void
{
// Ensure other WHERE predicates are passed through to the main WHERE clause
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id WHERE e.salary > 1000',
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e LEFT JOIN Doctrine\Tests\Models\Company\CompanyContract c ON c.salesPerson = e.id WHERE e.salary > 1000',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id LEFT JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra') WHERE c1_.salary > 1000",
);
}
Expand All @@ -2045,7 +2045,7 @@ public function testSingleTableInheritanceInnerJoinWithCondition(): void
{
// Test inner joins too
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e INNER JOIN Doctrine\Tests\Models\Company\CompanyContract c WITH c.salesPerson = e.id',
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyEmployee e INNER JOIN Doctrine\Tests\Models\Company\CompanyContract c ON c.salesPerson = e.id',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id INNER JOIN company_contracts c0_ ON (c0_.salesPerson_id = c2_.id) AND c0_.discr IN ('fix', 'flexible', 'flexultra')",
);
}
Expand All @@ -2056,7 +2056,7 @@ public function testSingleTableInheritanceLeftJoinNonAssociationWithConditionAnd
// Test that the discriminator IN() predicate is still added into
// the where clause when not joining onto that table
$this->assertSqlGeneration(
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c LEFT JOIN Doctrine\Tests\Models\Company\CompanyEmployee e WITH e.id = c.salesPerson WHERE c.completed = true',
'SELECT c FROM Doctrine\Tests\Models\Company\CompanyContract c LEFT JOIN Doctrine\Tests\Models\Company\CompanyEmployee e ON e.id = c.salesPerson WHERE c.completed = true',
"SELECT c0_.id AS id_0, c0_.completed AS completed_1, c0_.fixPrice AS fixPrice_2, c0_.hoursWorked AS hoursWorked_3, c0_.pricePerHour AS pricePerHour_4, c0_.maxPrice AS maxPrice_5, c0_.discr AS discr_6, c0_.salesPerson_id AS salesPerson_id_7 FROM company_contracts c0_ LEFT JOIN (company_employees c1_ INNER JOIN company_persons c2_ ON c1_.id = c2_.id LEFT JOIN company_managers c3_ ON c1_.id = c3_.id) ON (c2_.id = c0_.salesPerson_id) WHERE (c0_.completed = 1) AND c0_.discr IN ('fix', 'flexible', 'flexultra')",
);
}
Expand Down Expand Up @@ -2109,7 +2109,7 @@ public function testHavingSupportResultVariableLikeExpression(): void
public function testHavingSupportResultVariableNullComparisonExpression(): void
{
$this->assertSqlGeneration(
'SELECT u AS user, SUM(a.id) AS score FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN Doctrine\Tests\Models\CMS\CmsAddress a WITH a.user = u GROUP BY u HAVING score IS NOT NULL AND score >= 5',
'SELECT u AS user, SUM(a.id) AS score FROM Doctrine\Tests\Models\CMS\CmsUser u LEFT JOIN Doctrine\Tests\Models\CMS\CmsAddress a ON a.user = u GROUP BY u HAVING score IS NOT NULL AND score >= 5',
'SELECT c0_.id AS id_0, c0_.status AS status_1, c0_.username AS username_2, c0_.name AS name_3, SUM(c1_.id) AS sclr_4, c0_.email_id AS email_id_5 FROM cms_users c0_ LEFT JOIN cms_addresses c1_ ON (c1_.user_id = c0_.id) GROUP BY c0_.id, c0_.status, c0_.username, c0_.name, c0_.email_id HAVING sclr_4 IS NOT NULL AND sclr_4 >= 5',
);
}
Expand Down
Loading
Loading