3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 * This software consists of voluntary contributions made by many individuals
16 * and is licensed under the MIT license. For more information, see
17 * <http://www.doctrine-project.org>.
20 namespace Doctrine\ORM
;
22 use Doctrine\Common\Util\ClassUtils
;
23 use Doctrine\Common\Collections\Collection
;
24 use Doctrine\Common\Collections\ArrayCollection
;
26 use Doctrine\ORM\Query\Parameter
;
27 use Doctrine\ORM\Cache\QueryCacheKey
;
28 use Doctrine\DBAL\Cache\QueryCacheProfile
;
30 use Doctrine\ORM\Cache
;
31 use Doctrine\ORM\Query\ResultSetMapping
;
34 * Base contract for ORM queries. Base class for Query and NativeQuery.
36 * @link www.doctrine-project.org
38 * @author Benjamin Eberlei <kontakt@beberlei.de>
39 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
40 * @author Jonathan Wage <jonwage@gmail.com>
41 * @author Roman Borschel <roman@code-factory.org>
42 * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
44 abstract class AbstractQuery
46 /* Hydration mode constants */
49 * Hydrates an object graph. This is the default behavior.
51 const HYDRATE_OBJECT
= 1;
54 * Hydrates an array graph.
56 const HYDRATE_ARRAY
= 2;
59 * Hydrates a flat, rectangular result set with scalar values.
61 const HYDRATE_SCALAR
= 3;
64 * Hydrates a single scalar value.
66 const HYDRATE_SINGLE_SCALAR
= 4;
69 * Very simple object hydrator (optimized for performance).
71 const HYDRATE_SIMPLEOBJECT
= 5;
74 * The parameter map of this query.
76 * @var \Doctrine\Common\Collections\ArrayCollection
78 protected $parameters;
81 * The user-specified ResultSetMapping to use.
83 * @var \Doctrine\ORM\Query\ResultSetMapping
85 protected $_resultSetMapping;
88 * The entity manager used by this query object.
90 * @var EntityManagerInterface
95 * The map of query hints.
99 protected $_hints = array();
102 * The hydration mode.
106 protected $_hydrationMode = self
::HYDRATE_OBJECT
;
109 * @param \Doctrine\DBAL\Cache\QueryCacheProfile
111 protected $_queryCacheProfile;
114 * Whether or not expire the result cache.
118 protected $_expireResultCache = false;
121 * @param \Doctrine\DBAL\Cache\QueryCacheProfile
123 protected $_hydrationCacheProfile;
126 * Whether to use second level cache, if available.
130 protected $cacheable = false;
135 protected $hasCache = false;
138 * Second level cache region name.
142 protected $cacheRegion;
145 * Second level query cache mode.
149 protected $cacheMode;
152 * @var \Doctrine\ORM\Cache\Logging\CacheLogger|null
154 protected $cacheLogger;
159 protected $lifetime = 0;
162 * Initializes a new instance of a class derived from <tt>AbstractQuery</tt>.
164 * @param \Doctrine\ORM\EntityManagerInterface $em
166 public function __construct(EntityManagerInterface
$em)
169 $this->parameters
= new ArrayCollection();
170 $this->_hints
= $em->getConfiguration()->getDefaultQueryHints();
171 $this->hasCache
= $this->_em
->getConfiguration()->isSecondLevelCacheEnabled();
173 if ($this->hasCache
) {
174 $this->cacheLogger
= $em->getConfiguration()
175 ->getSecondLevelCacheConfiguration()
182 * Enable/disable second level query (result) caching for this query.
184 * @param boolean $cacheable
186 * @return static This query instance.
188 public function setCacheable($cacheable)
190 $this->cacheable
= (boolean
) $cacheable;
196 * @return boolean TRUE if the query results are enable for second level cache, FALSE otherwise.
198 public function isCacheable()
200 return $this->cacheable
;
204 * @param string $cacheRegion
206 * @return static This query instance.
208 public function setCacheRegion($cacheRegion)
210 $this->cacheRegion
= (string) $cacheRegion;
216 * Obtain the name of the second level query cache region in which query results will be stored
218 * @return The cache region name; NULL indicates the default region.
220 public function getCacheRegion()
222 return $this->cacheRegion
;
226 * @return boolean TRUE if the query cache and second level cache are enabled, FALSE otherwise.
228 protected function isCacheEnabled()
230 return $this->cacheable
&& $this->hasCache
;
236 public function getLifetime()
238 return $this->lifetime
;
242 * Sets the life-time for this query into second level cache.
244 * @param integer $lifetime
246 * @return static This query instance.
248 public function setLifetime($lifetime)
250 $this->lifetime
= (integer) $lifetime;
258 public function getCacheMode()
260 return $this->cacheMode
;
264 * @param integer $cacheMode
266 * @return static This query instance.
268 public function setCacheMode($cacheMode)
270 $this->cacheMode
= (integer) $cacheMode;
276 * Gets the SQL query that corresponds to this query object.
277 * The returned SQL syntax depends on the connection driver that is used
278 * by this query object at the time of this method call.
280 * @return string SQL query
282 abstract public function getSQL();
285 * Retrieves the associated EntityManager of this Query instance.
287 * @return \Doctrine\ORM\EntityManager
289 public function getEntityManager()
295 * Frees the resources used by the query object.
297 * Resets Parameters, Parameter Types and Query Hints.
301 public function free()
303 $this->parameters
= new ArrayCollection();
305 $this->_hints
= $this->_em
->getConfiguration()->getDefaultQueryHints();
309 * Get all defined parameters.
311 * @return \Doctrine\Common\Collections\ArrayCollection The defined query parameters.
313 public function getParameters()
315 return $this->parameters
;
319 * Gets a query parameter.
321 * @param mixed $key The key (index or name) of the bound parameter.
323 * @return Query\Parameter|null The value of the bound parameter, or NULL if not available.
325 public function getParameter($key)
327 $filteredParameters = $this->parameters
->filter(
328 function (Query\Parameter
$parameter) use ($key) {
329 $parameterName = $parameter->getName();
331 return $key === $parameterName ||
(string) $key === (string) $parameterName;
335 return ! $filteredParameters->isEmpty() ?
$filteredParameters->first() : null;
339 * Sets a collection of query parameters.
341 * @param \Doctrine\Common\Collections\ArrayCollection|array $parameters
343 * @return static This query instance.
345 public function setParameters($parameters)
347 // BC compatibility with 2.3-
348 if (is_array($parameters)) {
349 $parameterCollection = new ArrayCollection();
351 foreach ($parameters as $key => $value) {
352 $parameterCollection->add(new Parameter($key, $value));
355 $parameters = $parameterCollection;
358 $this->parameters
= $parameters;
364 * Sets a query parameter.
366 * @param string|int $key The parameter position or name.
367 * @param mixed $value The parameter value.
368 * @param string|null $type The parameter type. If specified, the given value will be run through
369 * the type conversion of this type. This is usually not needed for
370 * strings and numeric types.
372 * @return static This query instance.
374 public function setParameter($key, $value, $type = null)
376 $existingParameter = $this->getParameter($key);
378 if ($existingParameter !== null) {
379 $existingParameter->setValue($value, $type);
384 $this->parameters
->add(new Parameter($key, $value, $type));
390 * Processes an individual parameter value.
392 * @param mixed $value
396 * @throws \Doctrine\ORM\ORMInvalidArgumentException
398 public function processParameterValue($value)
400 if (is_scalar($value)) {
404 if ($value instanceof Collection
) {
405 $value = $value->toArray();
408 if (is_array($value)) {
409 foreach ($value as $key => $paramValue) {
410 $paramValue = $this->processParameterValue($paramValue);
411 $value[$key] = is_array($paramValue) ?
reset($paramValue) : $paramValue;
417 if (is_object($value) && $this->_em
->getMetadataFactory()->hasMetadataFor(ClassUtils
::getClass($value))) {
418 $value = $this->_em
->getUnitOfWork()->getSingleIdentifierValue($value);
420 if ($value === null) {
421 throw ORMInvalidArgumentException
::invalidIdentifierBindingEntity();
425 if ($value instanceof Mapping\ClassMetadata
) {
433 * Sets the ResultSetMapping that should be used for hydration.
435 * @param \Doctrine\ORM\Query\ResultSetMapping $rsm
437 * @return static This query instance.
439 public function setResultSetMapping(Query\ResultSetMapping
$rsm)
441 $this->translateNamespaces($rsm);
442 $this->_resultSetMapping
= $rsm;
448 * Gets the ResultSetMapping used for hydration.
450 * @return \Doctrine\ORM\Query\ResultSetMapping
452 protected function getResultSetMapping()
454 return $this->_resultSetMapping
;
458 * Allows to translate entity namespaces to full qualified names.
460 * @param Query\ResultSetMapping $rsm
464 private function translateNamespaces(Query\ResultSetMapping
$rsm)
466 $translate = function ($alias) {
467 return $this->_em
->getClassMetadata($alias)->getName();
470 $rsm->aliasMap
= array_map($translate, $rsm->aliasMap
);
471 $rsm->declaringClasses
= array_map($translate, $rsm->declaringClasses
);
475 * Set a cache profile for hydration caching.
477 * If no result cache driver is set in the QueryCacheProfile, the default
478 * result cache driver is used from the configuration.
480 * Important: Hydration caching does NOT register entities in the
481 * UnitOfWork when retrieved from the cache. Never use result cached
482 * entities for requests that also flush the EntityManager. If you want
483 * some form of caching with UnitOfWork registration you should use
484 * {@see AbstractQuery::setResultCacheProfile()}.
488 * $resultKey = "abc";
489 * $query->setHydrationCacheProfile(new QueryCacheProfile());
490 * $query->setHydrationCacheProfile(new QueryCacheProfile($lifetime, $resultKey));
492 * @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile
494 * @return static This query instance.
496 public function setHydrationCacheProfile(QueryCacheProfile
$profile = null)
498 if ( ! $profile->getResultCacheDriver()) {
499 $resultCacheDriver = $this->_em
->getConfiguration()->getHydrationCacheImpl();
500 $profile = $profile->setResultCacheDriver($resultCacheDriver);
503 $this->_hydrationCacheProfile
= $profile;
509 * @return \Doctrine\DBAL\Cache\QueryCacheProfile
511 public function getHydrationCacheProfile()
513 return $this->_hydrationCacheProfile
;
517 * Set a cache profile for the result cache.
519 * If no result cache driver is set in the QueryCacheProfile, the default
520 * result cache driver is used from the configuration.
522 * @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile
524 * @return static This query instance.
526 public function setResultCacheProfile(QueryCacheProfile
$profile = null)
528 if ($profile !== null && ! $profile->getResultCacheDriver()) {
529 $resultCacheDriver = $this->_em
->getConfiguration()->getResultCacheImpl();
530 $profile = $profile->setResultCacheDriver($resultCacheDriver);
533 $this->_queryCacheProfile
= $profile;
539 * Defines a cache driver to be used for caching result sets and implicitly enables caching.
541 * @param \Doctrine\Common\Cache\Cache|null $resultCacheDriver Cache driver
543 * @return static This query instance.
545 * @throws ORMException
547 public function setResultCacheDriver($resultCacheDriver = null)
549 if ($resultCacheDriver !== null && ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache
)) {
550 throw ORMException
::invalidResultCacheDriver();
553 $this->_queryCacheProfile
= $this->_queryCacheProfile
554 ?
$this->_queryCacheProfile
->setResultCacheDriver($resultCacheDriver)
555 : new QueryCacheProfile(0, null, $resultCacheDriver);
561 * Returns the cache driver used for caching result sets.
565 * @return \Doctrine\Common\Cache\Cache Cache driver
567 public function getResultCacheDriver()
569 if ($this->_queryCacheProfile
&& $this->_queryCacheProfile
->getResultCacheDriver()) {
570 return $this->_queryCacheProfile
->getResultCacheDriver();
573 return $this->_em
->getConfiguration()->getResultCacheImpl();
577 * Set whether or not to cache the results of this query and if so, for
578 * how long and which ID to use for the cache entry.
580 * @param boolean $bool
581 * @param integer $lifetime
582 * @param string $resultCacheId
584 * @return static This query instance.
586 public function useResultCache($bool, $lifetime = null, $resultCacheId = null)
589 $this->setResultCacheLifetime($lifetime);
590 $this->setResultCacheId($resultCacheId);
595 $this->_queryCacheProfile
= null;
601 * Defines how long the result cache will be active before expire.
603 * @param integer $lifetime How long the cache entry is valid.
605 * @return static This query instance.
607 public function setResultCacheLifetime($lifetime)
609 $lifetime = ($lifetime !== null) ?
(int) $lifetime : 0;
611 $this->_queryCacheProfile
= $this->_queryCacheProfile
612 ?
$this->_queryCacheProfile
->setLifetime($lifetime)
613 : new QueryCacheProfile($lifetime, null, $this->_em
->getConfiguration()->getResultCacheImpl());
619 * Retrieves the lifetime of resultset cache.
625 public function getResultCacheLifetime()
627 return $this->_queryCacheProfile ?
$this->_queryCacheProfile
->getLifetime() : 0;
631 * Defines if the result cache is active or not.
633 * @param boolean $expire Whether or not to force resultset cache expiration.
635 * @return static This query instance.
637 public function expireResultCache($expire = true)
639 $this->_expireResultCache
= $expire;
645 * Retrieves if the resultset cache is active or not.
649 public function getExpireResultCache()
651 return $this->_expireResultCache
;
655 * @return QueryCacheProfile
657 public function getQueryCacheProfile()
659 return $this->_queryCacheProfile
;
663 * Change the default fetch mode of an association for this query.
665 * $fetchMode can be one of ClassMetadata::FETCH_EAGER or ClassMetadata::FETCH_LAZY
667 * @param string $class
668 * @param string $assocName
669 * @param int $fetchMode
671 * @return static This query instance.
673 public function setFetchMode($class, $assocName, $fetchMode)
675 if ($fetchMode !== Mapping\ClassMetadata
::FETCH_EAGER
) {
676 $fetchMode = Mapping\ClassMetadata
::FETCH_LAZY
;
679 $this->_hints
['fetchMode'][$class][$assocName] = $fetchMode;
685 * Defines the processing mode to be used during hydration / result set transformation.
687 * @param integer $hydrationMode Doctrine processing mode to be used during hydration process.
688 * One of the Query::HYDRATE_* constants.
690 * @return static This query instance.
692 public function setHydrationMode($hydrationMode)
694 $this->_hydrationMode
= $hydrationMode;
700 * Gets the hydration mode currently used by the query.
704 public function getHydrationMode()
706 return $this->_hydrationMode
;
710 * Gets the list of results for the query.
712 * Alias for execute(null, $hydrationMode = HYDRATE_OBJECT).
714 * @param int $hydrationMode
718 public function getResult($hydrationMode = self
::HYDRATE_OBJECT
)
720 return $this->execute(null, $hydrationMode);
724 * Gets the array of results for the query.
726 * Alias for execute(null, HYDRATE_ARRAY).
730 public function getArrayResult()
732 return $this->execute(null, self
::HYDRATE_ARRAY
);
736 * Gets the scalar results for the query.
738 * Alias for execute(null, HYDRATE_SCALAR).
742 public function getScalarResult()
744 return $this->execute(null, self
::HYDRATE_SCALAR
);
748 * Get exactly one result or null.
750 * @param int $hydrationMode
754 * @throws NonUniqueResultException
756 public function getOneOrNullResult($hydrationMode = null)
759 $result = $this->execute(null, $hydrationMode);
760 } catch (NoResultException
$e) {
765 if ($this->_hydrationMode
!== self
::HYDRATE_SINGLE_SCALAR
&& ! $result) {
769 if ( ! is_array($result)) {
773 if (count($result) > 1) {
774 throw new NonUniqueResultException
;
777 return array_shift($result);
781 * Gets the single result of the query.
783 * Enforces the presence as well as the uniqueness of the result.
785 * If the result is not unique, a NonUniqueResultException is thrown.
786 * If there is no result, a NoResultException is thrown.
788 * @param integer $hydrationMode
792 * @throws NonUniqueResultException If the query result is not unique.
793 * @throws NoResultException If the query returned no result.
795 public function getSingleResult($hydrationMode = null)
797 $result = $this->execute(null, $hydrationMode);
799 if ($this->_hydrationMode
!== self
::HYDRATE_SINGLE_SCALAR
&& ! $result) {
800 throw new NoResultException
;
803 if ( ! is_array($result)) {
807 if (count($result) > 1) {
808 throw new NonUniqueResultException
;
811 return array_shift($result);
815 * Gets the single scalar result of the query.
817 * Alias for getSingleResult(HYDRATE_SINGLE_SCALAR).
821 * @throws NonUniqueResultException If the query result is not unique.
822 * @throws NoResultException If the query returned no result.
824 public function getSingleScalarResult()
826 return $this->getSingleResult(self
::HYDRATE_SINGLE_SCALAR
);
830 * Sets a query hint. If the hint name is not recognized, it is silently ignored.
832 * @param string $name The name of the hint.
833 * @param mixed $value The value of the hint.
835 * @return static This query instance.
837 public function setHint($name, $value)
839 $this->_hints
[$name] = $value;
845 * Gets the value of a query hint. If the hint name is not recognized, FALSE is returned.
847 * @param string $name The name of the hint.
849 * @return mixed The value of the hint or FALSE, if the hint name is not recognized.
851 public function getHint($name)
853 return isset($this->_hints
[$name]) ?
$this->_hints
[$name] : false;
857 * Check if the query has a hint
859 * @param string $name The name of the hint
861 * @return bool False if the query does not have any hint
863 public function hasHint($name)
865 return isset($this->_hints
[$name]);
869 * Return the key value map of query hints that are currently set.
873 public function getHints()
875 return $this->_hints
;
879 * Executes the query and returns an IterableResult that can be used to incrementally
880 * iterate over the result.
882 * @param ArrayCollection|array|null $parameters The query parameters.
883 * @param integer|null $hydrationMode The hydration mode to use.
885 * @return \Doctrine\ORM\Internal\Hydration\IterableResult
887 public function iterate($parameters = null, $hydrationMode = null)
889 if ($hydrationMode !== null) {
890 $this->setHydrationMode($hydrationMode);
893 if ( ! empty($parameters)) {
894 $this->setParameters($parameters);
897 $rsm = $this->getResultSetMapping();
898 $stmt = $this->_doExecute();
900 return $this->_em
->newHydrator($this->_hydrationMode
)->iterate($stmt, $rsm, $this->_hints
);
904 * Executes the query.
906 * @param ArrayCollection|array|null $parameters Query parameters.
907 * @param integer|null $hydrationMode Processing mode to be used during the hydration process.
911 public function execute($parameters = null, $hydrationMode = null)
913 if ($this->cacheable
&& $this->isCacheEnabled()) {
914 return $this->executeUsingQueryCache($parameters, $hydrationMode);
917 return $this->executeIgnoreQueryCache($parameters, $hydrationMode);
921 * Execute query ignoring second level cache.
923 * @param ArrayCollection|array|null $parameters
924 * @param integer|null $hydrationMode
928 private function executeIgnoreQueryCache($parameters = null, $hydrationMode = null)
930 if ($hydrationMode !== null) {
931 $this->setHydrationMode($hydrationMode);
934 if ( ! empty($parameters)) {
935 $this->setParameters($parameters);
938 $setCacheEntry = function() {};
940 if ($this->_hydrationCacheProfile
!== null) {
941 list($cacheKey, $realCacheKey) = $this->getHydrationCacheId();
943 $queryCacheProfile = $this->getHydrationCacheProfile();
944 $cache = $queryCacheProfile->getResultCacheDriver();
945 $result = $cache->fetch($cacheKey);
947 if (isset($result[$realCacheKey])) {
948 return $result[$realCacheKey];
955 $setCacheEntry = function($data) use ($cache, $result, $cacheKey, $realCacheKey, $queryCacheProfile) {
956 $result[$realCacheKey] = $data;
958 $cache->save($cacheKey, $result, $queryCacheProfile->getLifetime());
962 $stmt = $this->_doExecute();
964 if (is_numeric($stmt)) {
965 $setCacheEntry($stmt);
970 $rsm = $this->getResultSetMapping();
971 $data = $this->_em
->newHydrator($this->_hydrationMode
)->hydrateAll($stmt, $rsm, $this->_hints
);
973 $setCacheEntry($data);
979 * Load from second level cache or executes the query and put into cache.
981 * @param ArrayCollection|array|null $parameters
982 * @param integer|null $hydrationMode
986 private function executeUsingQueryCache($parameters = null, $hydrationMode = null)
988 $rsm = $this->getResultSetMapping();
989 $queryCache = $this->_em
->getCache()->getQueryCache($this->cacheRegion
);
990 $queryKey = new QueryCacheKey(
993 $this->cacheMode ?
: Cache
::MODE_NORMAL
,
994 $this->getTimestampKey()
997 $result = $queryCache->get($queryKey, $rsm, $this->_hints
);
999 if ($result !== null) {
1000 if ($this->cacheLogger
) {
1001 $this->cacheLogger
->queryCacheHit($queryCache->getRegion()->getName(), $queryKey);
1007 $result = $this->executeIgnoreQueryCache($parameters, $hydrationMode);
1008 $cached = $queryCache->put($queryKey, $rsm, $result, $this->_hints
);
1010 if ($this->cacheLogger
) {
1011 $this->cacheLogger
->queryCacheMiss($queryCache->getRegion()->getName(), $queryKey);
1014 $this->cacheLogger
->queryCachePut($queryCache->getRegion()->getName(), $queryKey);
1022 * @return \Doctrine\ORM\Cache\TimestampCacheKey|null
1024 private function getTimestampKey()
1026 $entityName = reset($this->_resultSetMapping
->aliasMap
);
1028 if (empty($entityName)) {
1032 $metadata = $this->_em
->getClassMetadata($entityName);
1034 return new Cache\
TimestampCacheKey($metadata->rootEntityName
);
1038 * Get the result cache id to use to store the result set cache entry.
1039 * Will return the configured id if it exists otherwise a hash will be
1040 * automatically generated for you.
1042 * @return array ($key, $hash)
1044 protected function getHydrationCacheId()
1046 $parameters = array();
1048 foreach ($this->getParameters() as $parameter) {
1049 $parameters[$parameter->getName()] = $this->processParameterValue($parameter->getValue());
1052 $sql = $this->getSQL();
1053 $queryCacheProfile = $this->getHydrationCacheProfile();
1054 $hints = $this->getHints();
1055 $hints['hydrationMode'] = $this->getHydrationMode();
1059 return $queryCacheProfile->generateCacheKeys($sql, $parameters, $hints);
1063 * Set the result cache id to use to store the result set cache entry.
1064 * If this is not explicitly set by the developer then a hash is automatically
1065 * generated for you.
1069 * @return static This query instance.
1071 public function setResultCacheId($id)
1073 $this->_queryCacheProfile
= $this->_queryCacheProfile
1074 ?
$this->_queryCacheProfile
->setCacheKey($id)
1075 : new QueryCacheProfile(0, $id, $this->_em
->getConfiguration()->getResultCacheImpl());
1081 * Get the result cache id to use to store the result set cache entry if set.
1087 public function getResultCacheId()
1089 return $this->_queryCacheProfile ?
$this->_queryCacheProfile
->getCacheKey() : null;
1093 * Executes the query and returns a the resulting Statement object.
1095 * @return \Doctrine\DBAL\Driver\Statement The executed database statement that holds the results.
1097 abstract protected function _doExecute();
1100 * Cleanup Query resource when clone is called.
1104 public function __clone()
1106 $this->parameters
= new ArrayCollection();
1108 $this->_hints
= array();
1109 $this->_hints
= $this->_em
->getConfiguration()->getDefaultQueryHints();
1113 * Generates a string of currently query to use for the cache second level cache.
1117 protected function getHash()
1119 $query = $this->getSQL();
1120 $hints = $this->getHints();
1121 $params = array_map(function(Parameter
$parameter) {
1122 // Small optimization
1123 // Does not invoke processParameterValue for scalar values
1124 if (is_scalar($value = $parameter->getValue())) {
1128 return $this->processParameterValue($value);
1129 }, $this->parameters
->getValues());
1133 return sha1($query . '-' . serialize($params) . '-' . serialize($hints));