| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620 | 
							- <?php
 - /*
 -  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 -  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 -  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 -  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 -  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 -  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 -  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 -  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 -  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 -  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 -  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 -  *
 -  * This software consists of voluntary contributions made by many individuals
 -  * and is licensed under the LGPL. For more information, see
 -  * <http://www.doctrine-project.org>.
 -  */
 - 
 - namespace Doctrine\ORM;
 - 
 - use Doctrine\DBAL\LockMode,
 -     Doctrine\ORM\Query\Parser,
 -     Doctrine\ORM\Query\QueryException;
 - 
 - /**
 -  * A Query object represents a DQL query.
 -  *
 -  * @since   1.0
 -  * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 -  * @author  Konsta Vesterinen <kvesteri@cc.hut.fi>
 -  * @author  Roman Borschel <roman@code-factory.org>
 -  */
 - final class Query extends AbstractQuery
 - {
 -     /* Query STATES */
 -     /**
 -      * A query object is in CLEAN state when it has NO unparsed/unprocessed DQL parts.
 -      */
 -     const STATE_CLEAN  = 1;
 -     /**
 -      * A query object is in state DIRTY when it has DQL parts that have not yet been
 -      * parsed/processed. This is automatically defined as DIRTY when addDqlQueryPart
 -      * is called.
 -      */
 -     const STATE_DIRTY = 2;
 - 
 -     /* Query HINTS */
 -     /**
 -      * The refresh hint turns any query into a refresh query with the result that
 -      * any local changes in entities are overridden with the fetched values.
 -      *
 -      * @var string
 -      */
 -     const HINT_REFRESH = 'doctrine.refresh';
 - 
 - 
 -     /**
 -      * Internal hint: is set to the proxy entity that is currently triggered for loading
 -      *
 -      * @var string
 -      */
 -     const HINT_REFRESH_ENTITY = 'doctrine.refresh.entity';
 - 
 -     /**
 -      * The forcePartialLoad query hint forces a particular query to return
 -      * partial objects.
 -      *
 -      * @var string
 -      * @todo Rename: HINT_OPTIMIZE
 -      */
 -     const HINT_FORCE_PARTIAL_LOAD = 'doctrine.forcePartialLoad';
 -     /**
 -      * The includeMetaColumns query hint causes meta columns like foreign keys and
 -      * discriminator columns to be selected and returned as part of the query result.
 -      *
 -      * This hint does only apply to non-object queries.
 -      *
 -      * @var string
 -      */
 -     const HINT_INCLUDE_META_COLUMNS = 'doctrine.includeMetaColumns';
 - 
 -     /**
 -      * An array of class names that implement \Doctrine\ORM\Query\TreeWalker and
 -      * are iterated and executed after the DQL has been parsed into an AST.
 -      *
 -      * @var string
 -      */
 -     const HINT_CUSTOM_TREE_WALKERS = 'doctrine.customTreeWalkers';
 - 
 -     /**
 -      * A string with a class name that implements \Doctrine\ORM\Query\TreeWalker
 -      * and is used for generating the target SQL from any DQL AST tree.
 -      *
 -      * @var string
 -      */
 -     const HINT_CUSTOM_OUTPUT_WALKER = 'doctrine.customOutputWalker';
 - 
 -     //const HINT_READ_ONLY = 'doctrine.readOnly';
 - 
 -     /**
 -      * @var string
 -      */
 -     const HINT_INTERNAL_ITERATION = 'doctrine.internal.iteration';
 - 
 -     /**
 -      * @var string
 -      */
 -     const HINT_LOCK_MODE = 'doctrine.lockMode';
 - 
 -     /**
 -      * @var integer $_state   The current state of this query.
 -      */
 -     private $_state = self::STATE_CLEAN;
 - 
 -     /**
 -      * @var string $_dql Cached DQL query.
 -      */
 -     private $_dql = null;
 - 
 -     /**
 -      * @var \Doctrine\ORM\Query\ParserResult  The parser result that holds DQL => SQL information.
 -      */
 -     private $_parserResult;
 - 
 -     /**
 -      * @var integer The first result to return (the "offset").
 -      */
 -     private $_firstResult = null;
 - 
 -     /**
 -      * @var integer The maximum number of results to return (the "limit").
 -      */
 -     private $_maxResults = null;
 - 
 -     /**
 -      * @var CacheDriver The cache driver used for caching queries.
 -      */
 -     private $_queryCache;
 - 
 -     /**
 -      * @var boolean Boolean value that indicates whether or not expire the query cache.
 -      */
 -     private $_expireQueryCache = false;
 - 
 -     /**
 -      * @var int Query Cache lifetime.
 -      */
 -     private $_queryCacheTTL;
 - 
 -     /**
 -      * @var boolean Whether to use a query cache, if available. Defaults to TRUE.
 -      */
 -     private $_useQueryCache = true;
 - 
 -     // End of Caching Stuff
 - 
 -     /**
 -      * Initializes a new Query instance.
 -      *
 -      * @param \Doctrine\ORM\EntityManager $entityManager
 -      */
 -     /*public function __construct(EntityManager $entityManager)
 -     {
 -         parent::__construct($entityManager);
 -     }*/
 - 
 -     /**
 -      * Gets the SQL query/queries that correspond to this DQL query.
 -      *
 -      * @return mixed The built sql query or an array of all sql queries.
 -      * @override
 -      */
 -     public function getSQL()
 -     {
 -         return $this->_parse()->getSQLExecutor()->getSQLStatements();
 -     }
 - 
 -     /**
 -      * Returns the corresponding AST for this DQL query.
 -      *
 -      * @return \Doctrine\ORM\Query\AST\SelectStatement |
 -      *         \Doctrine\ORM\Query\AST\UpdateStatement |
 -      *         \Doctrine\ORM\Query\AST\DeleteStatement
 -      */
 -     public function getAST()
 -     {
 -         $parser = new Parser($this);
 -         return $parser->getAST();
 -     }
 - 
 -     /**
 -      * Parses the DQL query, if necessary, and stores the parser result.
 -      *
 -      * Note: Populates $this->_parserResult as a side-effect.
 -      *
 -      * @return \Doctrine\ORM\Query\ParserResult
 -      */
 -     private function _parse()
 -     {
 -         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();
 -                 $queryCache->save($hash, $this->_parserResult, $this->_queryCacheTTL);
 -             } else {
 -                 // Cache hit.
 -                 $this->_parserResult = $cached;
 -             }
 -         } else {
 -             $parser = new Parser($this);
 -             $this->_parserResult = $parser->parse();
 -         }
 - 
 -         $this->_state = self::STATE_CLEAN;
 - 
 -         return $this->_parserResult;
 -     }
 - 
 -     /**
 -      * {@inheritdoc}
 -      */
 -     protected function _doExecute()
 -     {
 -         $executor = $this->_parse()->getSqlExecutor();
 - 
 -         // Prepare parameters
 -         $paramMappings = $this->_parserResult->getParameterMappings();
 - 
 -         if (count($paramMappings) != count($this->_params)) {
 -             throw QueryException::invalidParameterNumber();
 -         }
 - 
 -         list($sqlParams, $types) = $this->processParameterMappings($paramMappings);
 - 
 -         if ($this->_resultSetMapping === null) {
 -             $this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
 -         }
 - 
 -         return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
 -     }
 - 
 -     /**
 -      * Processes query parameter mappings
 -      *
 -      * @param array $paramMappings
 -      * @return array
 -      */
 -     private function processParameterMappings($paramMappings)
 -     {
 -         $sqlParams = $types = array();
 - 
 -         foreach ($this->_params as $key => $value) {
 -             if ( ! isset($paramMappings[$key])) {
 -                 throw QueryException::unknownParameter($key);
 -             }
 - 
 -             if (isset($this->_paramTypes[$key])) {
 -                 foreach ($paramMappings[$key] as $position) {
 -                     $types[$position] = $this->_paramTypes[$key];
 -                 }
 -             }
 - 
 -             $sqlPositions = $paramMappings[$key];
 -             $value = array_values($this->processParameterValue($value));
 -             $countValue = count($value);
 - 
 -             for ($i = 0, $l = count($sqlPositions); $i < $l; $i++) {
 -                 $sqlParams[$sqlPositions[$i]] = $value[($i % $countValue)];
 -             }
 -         }
 - 
 -         if (count($sqlParams) != count($types)) {
 -             throw QueryException::parameterTypeMissmatch();
 -         }
 - 
 -         if ($sqlParams) {
 -             ksort($sqlParams);
 -             $sqlParams = array_values($sqlParams);
 - 
 -             ksort($types);
 -             $types = array_values($types);
 -         }
 - 
 -         return array($sqlParams, $types);
 -     }
 - 
 -     /**
 -      * Process an individual parameter value
 -      *
 -      * @param mixed $value
 -      * @return array
 -      */
 -     private function processParameterValue($value)
 -     {
 -         if (is_array($value)) {
 -             for ($i = 0, $l = count($value); $i < $l; $i++) {
 -                 $paramValue = $this->processParameterValue($value[$i]);
 -                 
 -                 // TODO: What about Entities that have composite primary key?
 -                 $value[$i] = is_array($paramValue) ? $paramValue[key($paramValue)] : $paramValue;
 -             }
 -             
 -             return array($value);
 -         }
 -         
 -         if ( ! (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value)))) {
 -             return array($value);
 -         }
 -         
 -         if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) {
 -             return array_values($this->_em->getUnitOfWork()->getEntityIdentifier($value));
 -         }
 -         
 -         $class = $this->_em->getClassMetadata(get_class($value));
 -         
 -         return array_values($class->getIdentifierValues($value));
 -     }
 - 
 -     /**
 -      * Defines a cache driver to be used for caching queries.
 -      *
 -      * @param Doctrine_Cache_Interface|null $driver Cache driver
 -      * @return Query This query instance.
 -      */
 -     public function setQueryCacheDriver($queryCache)
 -     {
 -         $this->_queryCache = $queryCache;
 -         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.
 -      *
 -      * @return CacheDriver The cache driver used for query caching or NULL, if this
 -      * 					   Query does not use query caching.
 -      */
 -     public function getQueryCacheDriver()
 -     {
 -         if ($this->_queryCache) {
 -             return $this->_queryCache;
 -         } else {
 -             return $this->_em->getConfiguration()->getQueryCacheImpl();
 -         }
 -     }
 - 
 -     /**
 -      * Defines how long the query cache will be active before expire.
 -      *
 -      * @param integer $timeToLive How long the cache entry is valid
 -      * @return Query This query instance.
 -      */
 -     public function setQueryCacheLifetime($timeToLive)
 -     {
 -         if ($timeToLive !== null) {
 -             $timeToLive = (int) $timeToLive;
 -         }
 -         $this->_queryCacheTTL = $timeToLive;
 - 
 -         return $this;
 -     }
 - 
 -     /**
 -      * Retrieves the lifetime of resultset cache.
 -      *
 -      * @return int
 -      */
 -     public function getQueryCacheLifetime()
 -     {
 -         return $this->_queryCacheTTL;
 -     }
 - 
 -     /**
 -      * Defines if the query cache is active or not.
 -      *
 -      * @param boolean $expire Whether or not to force query cache expiration.
 -      * @return Query This query instance.
 -      */
 -     public function expireQueryCache($expire = true)
 -     {
 -         $this->_expireQueryCache = $expire;
 - 
 -         return $this;
 -     }
 - 
 -     /**
 -      * Retrieves if the query cache is active or not.
 -      *
 -      * @return bool
 -      */
 -     public function getExpireQueryCache()
 -     {
 -         return $this->_expireQueryCache;
 -     }
 - 
 -     /**
 -      * @override
 -      */
 -     public function free()
 -     {
 -         parent::free();
 -         $this->_dql = null;
 -         $this->_state = self::STATE_CLEAN;
 -     }
 - 
 -     /**
 -      * Sets a DQL query string.
 -      *
 -      * @param string $dqlQuery DQL Query
 -      * @return \Doctrine\ORM\AbstractQuery
 -      */
 -     public function setDQL($dqlQuery)
 -     {
 -         if ($dqlQuery !== null) {
 -             $this->_dql = $dqlQuery;
 -             $this->_state = self::STATE_DIRTY;
 -         }
 -         return $this;
 -     }
 - 
 -     /**
 -      * Returns the DQL query that is represented by this query object.
 -      *
 -      * @return string DQL query
 -      */
 -     public function getDQL()
 -     {
 -         return $this->_dql;
 -     }
 - 
 -     /**
 -      * Returns the state of this query object
 -      * By default the type is Doctrine_ORM_Query_Abstract::STATE_CLEAN but if it appears any unprocessed DQL
 -      * part, it is switched to Doctrine_ORM_Query_Abstract::STATE_DIRTY.
 -      *
 -      * @see AbstractQuery::STATE_CLEAN
 -      * @see AbstractQuery::STATE_DIRTY
 -      *
 -      * @return integer Return the query state
 -      */
 -     public function getState()
 -     {
 -         return $this->_state;
 -     }
 - 
 -     /**
 -      * Method to check if an arbitrary piece of DQL exists
 -      *
 -      * @param string $dql Arbitrary piece of DQL to check for
 -      * @return boolean
 -      */
 -     public function contains($dql)
 -     {
 -         return stripos($this->getDQL(), $dql) === false ? false : true;
 -     }
 - 
 -     /**
 -      * Sets the position of the first result to retrieve (the "offset").
 -      *
 -      * @param integer $firstResult The first result to return.
 -      * @return Query This query object.
 -      */
 -     public function setFirstResult($firstResult)
 -     {
 -         $this->_firstResult = $firstResult;
 -         $this->_state = self::STATE_DIRTY;
 -         return $this;
 -     }
 - 
 -     /**
 -      * Gets the position of the first result the query object was set to retrieve (the "offset").
 -      * Returns NULL if {@link setFirstResult} was not applied to this query.
 -      *
 -      * @return integer The position of the first result.
 -      */
 -     public function getFirstResult()
 -     {
 -         return $this->_firstResult;
 -     }
 - 
 -     /**
 -      * Sets the maximum number of results to retrieve (the "limit").
 -      *
 -      * @param integer $maxResults
 -      * @return Query This query object.
 -      */
 -     public function setMaxResults($maxResults)
 -     {
 -         $this->_maxResults = $maxResults;
 -         $this->_state = self::STATE_DIRTY;
 -         return $this;
 -     }
 - 
 -     /**
 -      * Gets the maximum number of results the query object was set to retrieve (the "limit").
 -      * Returns NULL if {@link setMaxResults} was not applied to this query.
 -      *
 -      * @return integer Maximum number of results.
 -      */
 -     public function getMaxResults()
 -     {
 -         return $this->_maxResults;
 -     }
 - 
 -     /**
 -      * Executes the query and returns an IterableResult that can be used to incrementally
 -      * iterated over the result.
 -      *
 -      * @param array $params The query parameters.
 -      * @param integer $hydrationMode The hydration mode to use.
 -      * @return IterableResult
 -      */
 -     public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT)
 -     {
 -         $this->setHint(self::HINT_INTERNAL_ITERATION, true);
 -         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);
 -     }
 - 
 -     /**
 -      * Set the lock mode for this Query.
 -      *
 -      * @see \Doctrine\DBAL\LockMode
 -      * @param  int $lockMode
 -      * @return Query
 -      */
 -     public function setLockMode($lockMode)
 -     {
 -         if ($lockMode == LockMode::PESSIMISTIC_READ || $lockMode == LockMode::PESSIMISTIC_WRITE) {
 -             if (!$this->_em->getConnection()->isTransactionActive()) {
 -                 throw TransactionRequiredException::transactionRequired();
 -             }
 -         }
 - 
 -         $this->setHint(self::HINT_LOCK_MODE, $lockMode);
 -         return $this;
 -     }
 - 
 -     /**
 -      * Get the current lock mode for this query.
 -      *
 -      * @return int
 -      */
 -     public function getLockMode()
 -     {
 -         $lockMode = $this->getHint(self::HINT_LOCK_MODE);
 -         if (!$lockMode) {
 -             return LockMode::NONE;
 -         }
 -         return $lockMode;
 -     }
 - 
 -     /**
 -      * Generate a cache id for the query cache - reusing the Result-Cache-Id generator.
 -      *
 -      * The query cache
 -      *
 -      * @return string
 -      */
 -     protected function _getQueryCacheId()
 -     {
 -         ksort($this->_hints);
 - 
 -         return md5(
 -             $this->getDql() . var_export($this->_hints, true) .
 -             '&firstResult=' . $this->_firstResult . '&maxResult=' . $this->_maxResults .
 -             '&hydrationMode='.$this->_hydrationMode.'DOCTRINE_QUERY_CACHE_SALT'
 -         );
 -     }
 - 
 -     /**
 -      * Cleanup Query resource when clone is called.
 -      *
 -      * @return void
 -      */
 -     public function __clone()
 -     {
 -         parent::__clone();
 -         $this->_state = self::STATE_DIRTY;
 -     }
 - }
 
 
  |