Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove legacy implementation of the DQL -> SQL transformation #11730

Open
wants to merge 1 commit into
base: 4.0.x
Choose a base branch
from
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
6 changes: 6 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Upgrade to 4.0

## Require implementation of `OutputWalker`, remove `SqlWalker::getExecutor()`

The `SqlWalker::getExecutor()` method is removed. Output walkers should
implement the `\Doctrine\ORM\Query\OutputWalker` interface and create
`Doctrine\ORM\Query\Exec\SqlFinalizer` instances.

## Remove `DatabaseDriver`

The class `Doctrine\ORM\Mapping\Driver\DatabaseDriver` is removed.
Expand Down
3 changes: 0 additions & 3 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -896,9 +896,6 @@
<ArgumentTypeCoercion>
<code><![CDATA[$stringPattern]]></code>
</ArgumentTypeCoercion>
<DeprecatedMethod>
<code><![CDATA[setSqlExecutor]]></code>
</DeprecatedMethod>
<InvalidNullableReturnType>
<code><![CDATA[AST\SelectStatement|AST\UpdateStatement|AST\DeleteStatement]]></code>
</InvalidNullableReturnType>
Expand Down
25 changes: 0 additions & 25 deletions src/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@
use Doctrine\DBAL\LockMode;
use Doctrine\DBAL\Result;
use Doctrine\DBAL\Types\Type;
use Doctrine\Deprecations\Deprecation;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\AST\DeleteStatement;
use Doctrine\ORM\Query\AST\SelectStatement;
use Doctrine\ORM\Query\AST\UpdateStatement;
use Doctrine\ORM\Query\Exec\AbstractSqlExecutor;
use Doctrine\ORM\Query\Exec\SqlFinalizer;
use Doctrine\ORM\Query\OutputWalker;
use Doctrine\ORM\Query\Parameter;
use Doctrine\ORM\Query\ParameterTypeInferer;
use Doctrine\ORM\Query\Parser;
Expand All @@ -30,7 +27,6 @@
use function count;
use function get_debug_type;
use function in_array;
use function is_a;
use function ksort;
use function md5;
use function reset;
Expand Down Expand Up @@ -665,31 +661,10 @@ protected function getQueryCacheId(): string
{
ksort($this->hints);

if (! $this->hasHint(self::HINT_CUSTOM_OUTPUT_WALKER)) {
// Assume Parser will create the SqlOutputWalker; save is_a call, which might trigger a class load
$firstAndMaxResult = '';
} else {
$outputWalkerClass = $this->getHint(self::HINT_CUSTOM_OUTPUT_WALKER);
if (is_a($outputWalkerClass, OutputWalker::class, true)) {
$firstAndMaxResult = '';
} else {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/11188/',
'Your output walker class %s should implement %s in order to provide a %s. This also means the output walker should not use the query firstResult/maxResult values, which should be read from the query by the SqlFinalizer only.',
$outputWalkerClass,
OutputWalker::class,
SqlFinalizer::class,
);
$firstAndMaxResult = '&firstResult=' . $this->firstResult . '&maxResult=' . $this->maxResults;
}
}

return md5(
$this->getDQL() . serialize($this->hints) .
'&platform=' . get_debug_type($this->getEntityManager()->getConnection()->getDatabasePlatform()) .
($this->em->hasFilters() ? $this->em->getFilters()->getHash() : '') .
$firstAndMaxResult .
'&hydrationMode=' . $this->hydrationMode . '&types=' . serialize($this->parsedTypes) . 'DOCTRINE_QUERY_CACHE_SALT',
);
}
Expand Down
40 changes: 2 additions & 38 deletions src/Query/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
namespace Doctrine\ORM\Query;

use Doctrine\Common\Lexer\Token;
use Doctrine\Deprecations\Deprecation;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Exception\DuplicateFieldException;
use Doctrine\ORM\Exception\NoMatchingPropertyException;
use Doctrine\ORM\Mapping\AssociationMapping;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\AST\Functions;
use Doctrine\ORM\Query\Exec\SqlFinalizer;
use LogicException;
use ReflectionClass;

Expand Down Expand Up @@ -158,7 +156,7 @@ final class Parser
/**
* The custom last tree walker, if any, that is responsible for producing the output.
*
* @var class-string<SqlWalker>|null
* @var class-string<OutputWalker>|null
*/
private $customOutputWalker;

Expand All @@ -177,24 +175,6 @@ public function __construct(private readonly Query $query)
$this->parserResult = new ParserResult();
}

/**
* Sets a custom tree walker that produces output.
* This tree walker will be run last over the AST, after any other walkers.
*
* @param class-string<SqlWalker> $className
*/
public function setCustomOutputTreeWalker(string $className): void
{
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/11641',
'%s is deprecated, set the output walker class with the \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER query hint instead',
__METHOD__,
);

$this->customOutputWalker = $className;
}

/**
* Adds a custom tree walker for modifying the AST.
*
Expand Down Expand Up @@ -359,23 +339,7 @@ public function parse(): ParserResult
$outputWalkerClass = $this->customOutputWalker ?: SqlOutputWalker::class;
$outputWalker = new $outputWalkerClass($this->query, $this->parserResult, $this->queryComponents);

if ($outputWalker instanceof OutputWalker) {
$finalizer = $outputWalker->getFinalizer($AST);
$this->parserResult->setSqlFinalizer($finalizer);
} else {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/11188/',
'Your output walker class %s should implement %s in order to provide a %s. This also means the output walker should not use the query firstResult/maxResult values, which should be read from the query by the SqlFinalizer only.',
$outputWalkerClass,
OutputWalker::class,
SqlFinalizer::class,
);
// @phpstan-ignore method.deprecated
$executor = $outputWalker->getExecutor($AST);
// @phpstan-ignore method.deprecated
$this->parserResult->setSqlExecutor($executor);
}
$this->parserResult->setSqlFinalizer($outputWalker->getFinalizer($AST));

return $this->parserResult;
}
Expand Down
16 changes: 0 additions & 16 deletions src/Query/SqlWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,22 +230,6 @@ public function setQueryComponent(string $dqlAlias, array $queryComponent): void
$this->queryComponents[$dqlAlias] = $queryComponent;
}

/**
* Gets an executor that can be used to execute the result of this walker.
*
* @deprecated Output walkers should no longer create the executor directly, but instead provide
* a SqlFinalizer by implementing the `OutputWalker` interface. Thus, this method is
* no longer needed and will be removed in 4.0.
*/
public function getExecutor(AST\SelectStatement|AST\UpdateStatement|AST\DeleteStatement $statement): Exec\AbstractSqlExecutor
{
return match (true) {
$statement instanceof AST\UpdateStatement => $this->createUpdateStatementExecutor($statement),
$statement instanceof AST\DeleteStatement => $this->createDeleteStatementExecutor($statement),
default => new Exec\SingleSelectExecutor($statement, $this),
};
}

/** @psalm-internal Doctrine\ORM */
protected function createUpdateStatementExecutor(AST\UpdateStatement $AST): Exec\AbstractSqlExecutor
{
Expand Down
3 changes: 2 additions & 1 deletion tests/Tests/ORM/Functional/PaginationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Doctrine\ORM\Query\AST\PathExpression;
use Doctrine\ORM\Query\AST\SelectStatement;
use Doctrine\ORM\Query\AST\WhereClause;
use Doctrine\ORM\Query\SqlOutputWalker;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\TreeWalkerAdapter;
use Doctrine\ORM\Tools\Pagination\Paginator;
Expand Down Expand Up @@ -643,7 +644,7 @@ public function testCountQueryStripsParametersInSelect(): void
self::assertCount(2, $getCountQuery->invoke($paginator)->getParameters());
self::assertCount(9, $paginator);

$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, SqlWalker::class);
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, SqlOutputWalker::class);

$paginator = new Paginator($query);

Expand Down
19 changes: 0 additions & 19 deletions tests/Tests/ORM/Functional/ParserResultSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,6 @@ protected function setUp(): void
parent::setUp();
}

/** @param Closure(ParserResult): ParserResult $toSerializedAndBack */
#[DataProvider('provideToSerializedAndBack')]
public function testSerializeParserResultForQueryWithSqlWalker(Closure $toSerializedAndBack): void
{
$query = $this->_em
->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyEmployee u WHERE u.name = :name');

// Use the (legacy) SqlWalker which directly puts an SqlExecutor instance into the parser result
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, Query\SqlWalker::class);

$parserResult = self::parseQuery($query);
$unserialized = $toSerializedAndBack($parserResult);

$this->assertInstanceOf(ParserResult::class, $unserialized);
$this->assertInstanceOf(ResultSetMapping::class, $unserialized->getResultSetMapping());
$this->assertEquals(['name' => [0]], $unserialized->getParameterMappings());
$this->assertNotNull($unserialized->prepareSqlExecutor($query));
}

/** @param Closure(ParserResult): ParserResult $toSerializedAndBack */
#[DataProvider('provideToSerializedAndBack')]
public function testSerializeParserResultForQueryWithSqlOutputWalker(Closure $toSerializedAndBack): void
Expand Down
Loading