Skip to content

Commit

Permalink
Support unserializing 2.14 ParserResult instances (#10684)
Browse files Browse the repository at this point in the history
  • Loading branch information
derrabus authored May 7, 2023
1 parent 60c625b commit 9bc6f5b
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 0 deletions.
24 changes: 24 additions & 0 deletions lib/Doctrine/ORM/Query/ParserResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use Doctrine\ORM\Query\Exec\AbstractSqlExecutor;

use function sprintf;

/**
* Encapsulates the resulting components from a DQL query parsing process that
* can be serialized.
Expand All @@ -14,6 +16,12 @@
*/
class ParserResult
{
private const LEGACY_PROPERTY_MAPPING = [
'sqlExecutor' => '_sqlExecutor',
'resultSetMapping' => '_resultSetMapping',
'parameterMappings' => '_parameterMappings',
];

/**
* The SQL executor used for executing the SQL.
*
Expand Down Expand Up @@ -122,4 +130,20 @@ public function getSqlParameterPositions($dqlPosition)
{
return $this->parameterMappings[$dqlPosition];
}

public function __wakeup(): void
{
$this->__unserialize((array) $this);
}

/** @param array<string, mixed> $data */
public function __unserialize(array $data): void
{
foreach (self::LEGACY_PROPERTY_MAPPING as $property => $legacyProperty) {
$this->$property = $data[sprintf("\0%s\0%s", self::class, $legacyProperty)]
?? $data[sprintf("\0%s\0%s", self::class, $property)]
?? $this->$property
?? null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional;

use Doctrine\ORM\Query;
use Doctrine\ORM\Query\Exec\SingleSelectExecutor;
use Doctrine\ORM\Query\ParserResult;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Tests\OrmFunctionalTestCase;
use Generator;
use ReflectionMethod;

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

class ParserResultSerializationTest extends OrmFunctionalTestCase
{
protected function setUp(): void
{
$this->useModelSet('company');

parent::setUp();
}

public function testSerializeParserResult(): void
{
$query = $this->_em
->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyEmployee u WHERE u.name = :name');

$parserResult = self::parseQuery($query);
$serialized = serialize($parserResult);
$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());
}

/**
* @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());
}

/** @return Generator<string, array{string}> */
public static function provideSerializedSingleSelectResults(): Generator
{
yield '2.14.3' => [file_get_contents(__DIR__ . '/ParserResults/single_select_2_14_3.txt')];
yield '2.15.0' => [file_get_contents(__DIR__ . '/ParserResults/single_select_2_15_0.txt')];
}

private static function parseQuery(Query $query): ParserResult
{
$r = new ReflectionMethod($query, 'parse');
$r->setAccessible(true);

return $r->invoke($query);
}
}
Binary file not shown.
Binary file not shown.

0 comments on commit 9bc6f5b

Please sign in to comment.