Skip to content

Commit

Permalink
[GH-7633] disallow cache partial objects (#8050)
Browse files Browse the repository at this point in the history
* [GH-7633] Bugfix: Partial queries were stored in 2LC.

There was a check in DefaultQueryCache that prevented partial queries,
because they are not supported. However the checked hint
Query::HINT_FORCE_PARTIAL_LOAD is optional, so cant be used to prevent
caching partial DQL queries.

Introduce a new hint that the SqlWalker sets on detecing a PARTIAL
query and throw an exception in the DefaultQueryCache if thats found.

* Housekeeping: CS

* [GH-7633] HINT_FORCE_PARTIAL_LOAD still needs to be checked.

* Housekeeping: Fix CS
  • Loading branch information
beberlei committed Mar 15, 2020
1 parent a9b6b72 commit a705f52
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/Doctrine/ORM/Cache/DefaultQueryCache.php
Expand Up @@ -260,7 +260,7 @@ public function put(QueryCacheKey $key, ResultSetMapping $rsm, $result, array $h
throw new CacheException("Second-level cache query supports only select statements.");
}

if (isset($hints[Query::HINT_FORCE_PARTIAL_LOAD]) && $hints[Query::HINT_FORCE_PARTIAL_LOAD]) {
if (($hints[Query\SqlWalker::HINT_PARTIAL] ?? false) === true || ($hints[Query::HINT_FORCE_PARTIAL_LOAD] ?? false) === true) {
throw new CacheException("Second level cache does not support partial entities.");
}

Expand Down
7 changes: 7 additions & 0 deletions lib/Doctrine/ORM/Query/SqlWalker.php
Expand Up @@ -46,6 +46,11 @@ class SqlWalker implements TreeWalker
*/
const HINT_DISTINCT = 'doctrine.distinct';

/**
* Used to mark a query as containing a PARTIAL expression, which needs to be known by SLC.
*/
public const HINT_PARTIAL = 'doctrine.partial';

/**
* @var ResultSetMapping
*/
Expand Down Expand Up @@ -1366,6 +1371,8 @@ public function walkSelectExpression($selectExpression)
default:
// IdentificationVariable or PartialObjectExpression
if ($expr instanceof AST\PartialObjectExpression) {
$this->query->setHint(self::HINT_PARTIAL, true);

$dqlAlias = $expr->identificationVariable;
$partialFieldSet = $expr->partialFieldSet;
} else {
Expand Down
Expand Up @@ -1095,11 +1095,25 @@ public function testCacheablePartialQueryException()
$this->loadFixturesCountries();

$this->_em->createQuery("SELECT PARTIAL c.{id} FROM Doctrine\Tests\Models\Cache\Country c")
->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
->setCacheable(true)
->getResult();
}

/**
* @expectedException \Doctrine\ORM\Cache\CacheException
* @expectedExceptionMessage Second level cache does not support partial entities.
*/
public function testCacheableForcePartialLoadHintQueryException()
{
$this->evictRegions();
$this->loadFixturesCountries();

$this->_em->createQuery('SELECT c FROM Doctrine\Tests\Models\Cache\Country c')
->setCacheable(true)
->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
->getResult();
}

/**
* @expectedException \Doctrine\ORM\Cache\CacheException
* @expectedExceptionMessage Second-level cache query supports only select statements.
Expand Down

0 comments on commit a705f52

Please sign in to comment.