123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620 |
- <?php
-
-
- namespace Doctrine\ORM;
-
- use Doctrine\DBAL\LockMode,
- Doctrine\ORM\Query\Parser,
- Doctrine\ORM\Query\QueryException;
-
-
- final class Query extends AbstractQuery
- {
-
-
-
- const STATE_CLEAN = 1;
-
-
- const STATE_DIRTY = 2;
-
-
-
-
- const HINT_REFRESH = 'doctrine.refresh';
-
-
-
-
- const HINT_REFRESH_ENTITY = 'doctrine.refresh.entity';
-
-
-
- const HINT_FORCE_PARTIAL_LOAD = 'doctrine.forcePartialLoad';
-
-
- const HINT_INCLUDE_META_COLUMNS = 'doctrine.includeMetaColumns';
-
-
-
- const HINT_CUSTOM_TREE_WALKERS = 'doctrine.customTreeWalkers';
-
-
-
- const HINT_CUSTOM_OUTPUT_WALKER = 'doctrine.customOutputWalker';
-
-
-
-
-
- const HINT_INTERNAL_ITERATION = 'doctrine.internal.iteration';
-
-
-
- const HINT_LOCK_MODE = 'doctrine.lockMode';
-
-
-
- private $_state = self::STATE_CLEAN;
-
-
-
- private $_dql = null;
-
-
-
- private $_parserResult;
-
-
-
- private $_firstResult = null;
-
-
-
- private $_maxResults = null;
-
-
-
- private $_queryCache;
-
-
-
- private $_expireQueryCache = false;
-
-
-
- private $_queryCacheTTL;
-
-
-
- private $_useQueryCache = true;
-
-
-
-
-
-
-
-
-
-
- public function getSQL()
- {
- return $this->_parse()->getSQLExecutor()->getSQLStatements();
- }
-
-
-
- public function getAST()
- {
- $parser = new Parser($this);
- return $parser->getAST();
- }
-
-
-
- private function _parse()
- {
- if ($this->_state === self::STATE_CLEAN) {
- return $this->_parserResult;
- }
-
-
- if ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver())) {
- $hash = $this->_getQueryCacheId();
- $cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash);
-
- if ($cached === false) {
-
- $parser = new Parser($this);
- $this->_parserResult = $parser->parse();
- $queryCache->save($hash, $this->_parserResult, $this->_queryCacheTTL);
- } else {
-
- $this->_parserResult = $cached;
- }
- } else {
- $parser = new Parser($this);
- $this->_parserResult = $parser->parse();
- }
-
- $this->_state = self::STATE_CLEAN;
-
- return $this->_parserResult;
- }
-
-
-
- protected function _doExecute()
- {
- $executor = $this->_parse()->getSqlExecutor();
-
-
- $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);
- }
-
-
-
- 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);
- }
-
-
-
- private function processParameterValue($value)
- {
- if (is_array($value)) {
- for ($i = 0, $l = count($value); $i < $l; $i++) {
- $paramValue = $this->processParameterValue($value[$i]);
-
-
- $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));
- }
-
-
-
- public function setQueryCacheDriver($queryCache)
- {
- $this->_queryCache = $queryCache;
- return $this;
- }
-
-
-
- public function useQueryCache($bool)
- {
- $this->_useQueryCache = $bool;
- return $this;
- }
-
-
-
- public function getQueryCacheDriver()
- {
- if ($this->_queryCache) {
- return $this->_queryCache;
- } else {
- return $this->_em->getConfiguration()->getQueryCacheImpl();
- }
- }
-
-
-
- public function setQueryCacheLifetime($timeToLive)
- {
- if ($timeToLive !== null) {
- $timeToLive = (int) $timeToLive;
- }
- $this->_queryCacheTTL = $timeToLive;
-
- return $this;
- }
-
-
-
- public function getQueryCacheLifetime()
- {
- return $this->_queryCacheTTL;
- }
-
-
-
- public function expireQueryCache($expire = true)
- {
- $this->_expireQueryCache = $expire;
-
- return $this;
- }
-
-
-
- public function getExpireQueryCache()
- {
- return $this->_expireQueryCache;
- }
-
-
-
- public function free()
- {
- parent::free();
- $this->_dql = null;
- $this->_state = self::STATE_CLEAN;
- }
-
-
-
- public function setDQL($dqlQuery)
- {
- if ($dqlQuery !== null) {
- $this->_dql = $dqlQuery;
- $this->_state = self::STATE_DIRTY;
- }
- return $this;
- }
-
-
-
- public function getDQL()
- {
- return $this->_dql;
- }
-
-
-
- public function getState()
- {
- return $this->_state;
- }
-
-
-
- public function contains($dql)
- {
- return stripos($this->getDQL(), $dql) === false ? false : true;
- }
-
-
-
- public function setFirstResult($firstResult)
- {
- $this->_firstResult = $firstResult;
- $this->_state = self::STATE_DIRTY;
- return $this;
- }
-
-
-
- public function getFirstResult()
- {
- return $this->_firstResult;
- }
-
-
-
- public function setMaxResults($maxResults)
- {
- $this->_maxResults = $maxResults;
- $this->_state = self::STATE_DIRTY;
- return $this;
- }
-
-
-
- public function getMaxResults()
- {
- return $this->_maxResults;
- }
-
-
-
- public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT)
- {
- $this->setHint(self::HINT_INTERNAL_ITERATION, true);
- return parent::iterate($params, $hydrationMode);
- }
-
-
-
- public function setHint($name, $value)
- {
- $this->_state = self::STATE_DIRTY;
- return parent::setHint($name, $value);
- }
-
-
-
- public function setHydrationMode($hydrationMode)
- {
- $this->_state = self::STATE_DIRTY;
- return parent::setHydrationMode($hydrationMode);
- }
-
-
-
- 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;
- }
-
-
-
- public function getLockMode()
- {
- $lockMode = $this->getHint(self::HINT_LOCK_MODE);
- if (!$lockMode) {
- return LockMode::NONE;
- }
- return $lockMode;
- }
-
-
-
- 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'
- );
- }
-
-
-
- public function __clone()
- {
- parent::__clone();
- $this->_state = self::STATE_DIRTY;
- }
- }
|