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
11 changes: 11 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Upgrade to 4.0

## BC BREAK: Internal structure of `Doctrine\ORM\Query\ParserResult` changed

The internal structure of `Doctrine\ORM\Query\ParserResult` changed. Thus, it is no longer possible to unserialize cached parser result instances that
were created and serialized with the previous major version of the ORM.

You need to clear your query cache when upgrading to the new major version.

## BC BREAK: `Doctrine\ORM\Query\ParserResult` no longer holds `AbstractSqlExecutor`, `Doctrine\ORM\Query\Exec\SingleSelectExecutor` is removed

This finishes the refactoring started in https://github.com/doctrine/orm/pull/11188: `ParserResult` has to be provided with an `Doctrine\ORM\Query\Exec\SqlFinalizer`. The `SingleSelectExecutor` is removed since it has been replaced by `SingleSelectSqlFinalizer`.

## BC BREAK: throw on `nullable` on columns that end up being used in a primary key

Specifying `nullable` on join columns that are part of a primary key is
Expand Down
6 changes: 0 additions & 6 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2280,12 +2280,6 @@ parameters:
count: 1
path: src/Query/Exec/MultiTableUpdateExecutor.php

-
message: '#^Parameter \#1 \$sql of method Doctrine\\DBAL\\Connection\:\:executeQuery\(\) expects string, list\<string\>\|string given\.$#'
identifier: argument.type
count: 1
path: src/Query/Exec/SingleSelectExecutor.php

-
message: '#^Method Doctrine\\ORM\\Query\\Exec\\SingleTableDeleteUpdateExecutor\:\:execute\(\) should return int but returns int\|string\.$#'
identifier: return.type
Expand Down
31 changes: 0 additions & 31 deletions src/Query/Exec/SingleSelectExecutor.php

This file was deleted.

44 changes: 3 additions & 41 deletions src/Query/ParserResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
use Doctrine\ORM\Query\Exec\SqlFinalizer;
use LogicException;

use function sprintf;

/**
* Encapsulates the resulting components from a DQL query parsing process that
* can be serialized.
Expand All @@ -19,11 +17,6 @@
*/
class ParserResult
{
/**
* The SQL executor used for executing the SQL.
*/
private AbstractSqlExecutor|null $sqlExecutor = null;

/**
* The SQL executor used for executing the SQL.
*/
Expand Down Expand Up @@ -68,49 +61,18 @@ public function setResultSetMapping(ResultSetMapping $rsm): void
$this->resultSetMapping = $rsm;
}

/**
* Sets the SQL executor that should be used for this ParserResult.
*
* @deprecated
*/
public function setSqlExecutor(AbstractSqlExecutor $executor): void
{
$this->sqlExecutor = $executor;
}

/**
* Gets the SQL executor used by this ParserResult.
*
* @deprecated
*/
public function getSqlExecutor(): AbstractSqlExecutor
{
if ($this->sqlExecutor === null) {
throw new LogicException(sprintf(
'Executor not set yet. Call %s::setSqlExecutor() first.',
self::class,
));
}

return $this->sqlExecutor;
}

public function setSqlFinalizer(SqlFinalizer $finalizer): void
{
$this->sqlFinalizer = $finalizer;
}

public function prepareSqlExecutor(Query $query): AbstractSqlExecutor
{
if ($this->sqlFinalizer !== null) {
return $this->sqlFinalizer->createExecutor($query);
}

if ($this->sqlExecutor !== null) {
return $this->sqlExecutor;
if ($this->sqlFinalizer === null) {
throw new LogicException('No SqlFinalizer has been set; this ParserResult is incomplete.');
}

throw new LogicException('This ParserResult lacks both the SqlFinalizer as well as the (legacy) SqlExecutor');
return $this->sqlFinalizer->createExecutor($query);
}

/**
Expand Down
21 changes: 0 additions & 21 deletions tests/Tests/ORM/Functional/ParserResultSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\Exec\FinalizedSelectExecutor;
use Doctrine\ORM\Query\Exec\PreparedExecutorFinalizer;
use Doctrine\ORM\Query\Exec\SingleSelectExecutor;
use Doctrine\ORM\Query\ParserResult;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Tests\OrmFunctionalTestCase;
Expand All @@ -18,8 +17,6 @@
use Symfony\Component\VarExporter\Instantiator;
use Symfony\Component\VarExporter\VarExporter;

use function file_get_contents;
use function rtrim;
use function serialize;
use function unserialize;

Expand Down Expand Up @@ -69,24 +66,6 @@ static function (ParserResult $parserResult): ParserResult {
];
}

#[DataProvider('provideSerializedSingleSelectResults')]
public function testUnserializeSingleSelectResult(string $serialized): void
{
$unserialized = unserialize($serialized);

$this->assertInstanceOf(ParserResult::class, $unserialized);
$this->assertInstanceOf(ResultSetMapping::class, $unserialized->getResultSetMapping());
$this->assertEquals(['name' => [0]], $unserialized->getParameterMappings());
$this->assertInstanceOf(SingleSelectExecutor::class, $unserialized->getSqlExecutor());
$this->assertIsString($unserialized->getSqlExecutor()->getSqlStatements());
}

/** @return Generator<string, array{string}> */
public static function provideSerializedSingleSelectResults(): Generator
{
yield '2.17.0' => [rtrim(file_get_contents(__DIR__ . '/ParserResults/single_select_2_17_0.txt'), "\n")];
}

public function testSymfony44ProvidedData(): void
{
$sqlExecutor = new FinalizedSelectExecutor('test');
Expand Down
Binary file not shown.
6 changes: 5 additions & 1 deletion tests/Tests/ORM/Functional/QueryCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\DBAL\Connection;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\Exec\AbstractSqlExecutor;
use Doctrine\ORM\Query\Exec\SqlFinalizer;
use Doctrine\ORM\Query\ParserResult;
use Doctrine\Tests\OrmFunctionalTestCase;
use PHPUnit\Framework\Attributes\Depends;
Expand Down Expand Up @@ -130,8 +131,11 @@ public function execute(Connection $conn, array $params, array $types): int
}
};

$sqlFinalizerMock = $this->createMock(SqlFinalizer::class);
$sqlFinalizerMock->method('createExecutor')->with($query)->willReturn($sqlExecutorStub);

$parserResultMock = new ParserResult();
$parserResultMock->setSqlExecutor($sqlExecutorStub);
$parserResultMock->setSqlFinalizer($sqlFinalizerMock);

$cache = $this->createMock(CacheItemPoolInterface::class);

Expand Down
19 changes: 0 additions & 19 deletions tests/Tests/ORM/Query/ParserResultTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

namespace Doctrine\Tests\ORM\Query;

use Doctrine\ORM\Query\Exec\AbstractSqlExecutor;
use Doctrine\ORM\Query\ParserResult;
use Doctrine\ORM\Query\ResultSetMapping;
use LogicException;
use PHPUnit\Framework\TestCase;

class ParserResultTest extends TestCase
Expand All @@ -25,23 +23,6 @@ public function testGetRsm(): void
self::assertInstanceOf(ResultSetMapping::class, $this->parserResult->getResultSetMapping());
}

public function testItThrowsWhenAttemptingToAccessTheExecutorBeforeItIsSet(): void
{
$this->expectException(LogicException::class);
$this->expectExceptionMessage(
'Executor not set yet. Call Doctrine\ORM\Query\ParserResult::setSqlExecutor() first.',
);

$this->parserResult->getSqlExecutor();
}

public function testSetGetSqlExecutor(): void
{
$executor = $this->createMock(AbstractSqlExecutor::class);
$this->parserResult->setSqlExecutor($executor);
self::assertSame($executor, $this->parserResult->getSqlExecutor());
}

public function testGetSqlParameterPosition(): void
{
$this->parserResult->addParameterMapping(1, 1);
Expand Down
Loading