Commit e235044c authored by romanb's avatar romanb

[2.0] Fixed query and result cache to work nice together and avoid unnecessary cache lookups.

parent 1e664156
......@@ -477,7 +477,7 @@ abstract class AbstractQuery
}
if ($hydrationMode !== null) {
$this->_hydrationMode = $hydrationMode;
$this->setHydrationMode($hydrationMode);
}
$params = $this->getParameters($params);
......
......@@ -157,9 +157,9 @@ class ObjectHydrator extends AbstractHydrator
$this->_initializedCollections[$oid . $fieldName] = $value;
} else if (isset($this->_hints[Query::HINT_REFRESH])) {
// Is already PersistentCollection, but REFRESH
$value->clear();
$value->setDirty(false);
$value->setInitialized(true);
$value->unwrap()->clear();
$this->_initializedCollections[$oid . $fieldName] = $value;
} else {
// Is already PersistentCollection, and DONT REFRESH
......@@ -360,10 +360,10 @@ class ObjectHydrator extends AbstractHydrator
if (isset($targetClass->inverseMappings[$relation->sourceEntityName][$relationField])) {
$inverseAssoc = $targetClass->inverseMappings[$relation->sourceEntityName][$relationField];
if ($inverseAssoc->isOneToMany()) {
// Only initialize reverse collection if it is not yet initialized.
/*// Only initialize reverse collection if it is not yet initialized.
if ( ! isset($this->_initializedCollections[spl_object_hash($element) . $inverseAssoc->sourceFieldName])) {
$this->_initRelatedCollection($element, $targetClass, $inverseAssoc->sourceFieldName);
}
}*/
} else {
$targetClass->reflFields[$inverseAssoc->sourceFieldName]->setValue($element, $parentObject);
$this->_uow->setOriginalEntityProperty(spl_object_hash($element), $inverseAssoc->sourceFieldName, $parentObject);
......
......@@ -122,6 +122,11 @@ final class Query extends AbstractQuery
*/
private $_queryCacheTTL;
/**
* @var boolean Whether to use a query cache, if available. Defaults to TRUE.
*/
private $_useQueryCache = true;
// End of Caching Stuff
/**
......@@ -154,11 +159,29 @@ final class Query extends AbstractQuery
*/
private function _parse()
{
if ($this->_state === self::STATE_DIRTY) {
if ($this->_state === self::STATE_CLEAN) {
return $this->_parserResult;
}
// Check query cache.
if ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver())) {
$hash = $this->_getQueryCacheId();
$cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash);
if ($cached === false) {
// Cache miss.
$parser = new Parser($this);
$this->_parserResult = $parser->parse();
$this->_state = self::STATE_CLEAN;
$queryCache->save($hash, $this->_parserResult, null);
} else {
// Cache hit.
$this->_parserResult = $cached;
}
} else {
$parser = new Parser($this);
$this->_parserResult = $parser->parse();
}
$this->_state = self::STATE_CLEAN;
return $this->_parserResult;
}
......@@ -171,26 +194,8 @@ final class Query extends AbstractQuery
*/
protected function _doExecute(array $params)
{
// Check query cache
if ($queryCache = $this->getQueryCacheDriver()) {
$hash = $this->_getQueryCacheId();
$cached = ($this->_expireQueryCache) ? false : $queryCache->fetch($hash);
if ($cached === false) {
// Cache miss.
$executor = $this->_parse()->getSqlExecutor();
$queryCache->save($hash, $this->_parserResult, null);
} else {
// Cache hit.
$this->_parserResult = $cached;
$executor = $this->_parserResult->getSqlExecutor();
}
} else {
$executor = $this->_parse()->getSqlExecutor();
}
$params = $this->_prepareParams($params);
if ( ! $this->_resultSetMapping) {
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
}
......@@ -252,6 +257,18 @@ final class Query extends AbstractQuery
return $this;
}
/**
* Defines whether the query should make use of a query cache, if available.
*
* @param boolean $bool
* @return @return Query This query instance.
*/
public function useQueryCache($bool)
{
$this->_useQueryCache = $bool;
return $this;
}
/**
* Returns the cache driver used for query caching.
*
......@@ -386,6 +403,7 @@ final class Query extends AbstractQuery
public function setFirstResult($firstResult)
{
$this->_firstResult = $firstResult;
$this->_state = self::STATE_DIRTY;
return $this;
}
......@@ -409,6 +427,7 @@ final class Query extends AbstractQuery
public function setMaxResults($maxResults)
{
$this->_maxResults = $maxResults;
$this->_state = self::STATE_DIRTY;
return $this;
}
......@@ -437,6 +456,24 @@ final class Query extends AbstractQuery
return parent::iterate($params, $hydrationMode);
}
/**
* {@inheritdoc}
*/
public function setHint($name, $value)
{
$this->_state = self::STATE_DIRTY;
return parent::setHint($name, $value);
}
/**
* {@inheritdoc}
*/
public function setHydrationMode($hydrationMode)
{
$this->_state = self::STATE_DIRTY;
return parent::setHydrationMode($hydrationMode);
}
/**
* Generate a cache id for the query cache - reusing the Result-Cache-Id generator.
*
......
......@@ -47,6 +47,7 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
$cacheCount = count($cache->getIds());
$query->setFirstResult(10);
$query->setMaxResults(9999);
$query->getResult();
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
......
......@@ -20,7 +20,8 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
try {
$query = $this->_em->createQuery($dqlToBeTested);
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
->useQueryCache(false);
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
$query->free();
} catch (\Exception $e) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment