/** * Calculates total count of query records * * @param Query $query * @param \Doctrine\Common\Collections\ArrayCollection|array|null $parameters Query parameters. * @return integer */ public function getCount(Query $query, $parameters = null) { if (!empty($parameters)) { $query = clone $query; $query->setParameters($parameters); } $parser = new Parser($query); $parserResult = $parser->parse(); $parameterMappings = $parserResult->getParameterMappings(); list($sqlParameters, $parameterTypes) = $this->processParameterMappings($query, $parameterMappings); $statement = $query->getEntityManager()->getConnection()->executeQuery('SELECT COUNT(*) FROM (' . $query->getSQL() . ') AS e', $sqlParameters, $parameterTypes); $result = $statement->fetchColumn(); return $result ? (int) $result : 0; }
/** * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * * Copy of Doctrine\ORM\Query::processParameterMappings * * @param Query $query * @return array * @throws QueryException */ public function processParameterMappings(Query $query) { $parser = new Parser($query); $parseResult = $parser->parse(); $paramMappings = $parseResult->getParameterMappings(); $resultSetMapping = $parseResult->getResultSetMapping(); $paramCount = count($query->getParameters()); $mappingCount = count($paramMappings); if ($paramCount > $mappingCount) { throw QueryException::tooManyParameters($mappingCount, $paramCount); } elseif ($paramCount < $mappingCount) { throw QueryException::tooFewParameters($mappingCount, $paramCount); } $sqlParams = []; $types = []; foreach ($query->getParameters() as $parameter) { $key = $parameter->getName(); $value = $parameter->getValue(); $rsm = $resultSetMapping; if (!isset($paramMappings[$key])) { throw QueryException::unknownParameter($key); } if (isset($rsm->metadataParameterMapping[$key]) && $value instanceof ClassMetadata) { $value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]); } $value = $query->processParameterValue($value); $type = $parameter->getValue() === $value ? $parameter->getType() : Query\ParameterTypeInferer::inferType($value); foreach ($paramMappings[$key] as $position) { $types[$position] = $type; } $sqlPositions = $paramMappings[$key]; // optimized multi value sql positions away for now, // they are not allowed in DQL anyways. $value = [$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::parameterTypeMismatch(); } if ($sqlParams) { ksort($sqlParams); $sqlParams = array_values($sqlParams); ksort($types); $types = array_values($types); } return [$sqlParams, $types]; }
/** * Calculates total count of query records * Notes: this method do not make any modifications of the given query * * @param Query $query * * @return integer */ public function getCount(Query $query) { if ($this->useWalker($query)) { if (!$query->contains('DISTINCT')) { $query->setHint(CountWalker::HINT_DISTINCT, false); } // fix of doctrine count walker bug // TODO revert changes when doctrine version >= 2.5 in scope of BAP-5577 /* @var $countQuery Query */ $countQuery = clone $query; $countQuery->setParameters(clone $query->getParameters()); foreach ($query->getHints() as $name => $value) { $countQuery->setHint($name, $value); } if (!$countQuery->hasHint(CountWalker::HINT_DISTINCT)) { $countQuery->setHint(CountWalker::HINT_DISTINCT, true); } $this->appendTreeWalker($countQuery, 'Oro\\Bundle\\BatchBundle\\ORM\\Query\\Walker\\CountWalker'); $countQuery->setFirstResult(null)->setMaxResults(null); try { $data = $countQuery->getScalarResult(); $data = array_map('current', $data); $result = array_sum($data); } catch (NoResultException $e) { $result = 0; } } else { $parser = new Parser($query); $parserResult = $parser->parse(); $parameterMappings = $parserResult->getParameterMappings(); list($sqlParameters, $parameterTypes) = $this->processParameterMappings($query, $parameterMappings); $statement = $query->getEntityManager()->getConnection()->executeQuery('SELECT COUNT(*) FROM (' . $query->getSQL() . ') AS e', $sqlParameters, $parameterTypes); $result = $statement->fetchColumn(); } return $result ? (int) $result : 0; }
/** * 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() { // Return previous parser result if the query and the filter collection are both clean if ($this->_state === self::STATE_CLEAN && $this->_em->isFiltersStateClean()) { return $this->_parserResult; } $this->_state = self::STATE_CLEAN; // Check query cache. if (!($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver()))) { $parser = new Parser($this); $this->_parserResult = $parser->parse(); return $this->_parserResult; } $hash = $this->_getQueryCacheId(); $cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash); if ($cached !== false) { // Cache hit. $this->_parserResult = $cached; return $this->_parserResult; } // Cache miss. $parser = new Parser($this); $this->_parserResult = $parser->parse(); $queryCache->save($hash, $this->_parserResult, $this->_queryCacheTTL); return $this->_parserResult; }
/** * 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; }
/** * Returns Query prepared to count. * * @return Query */ private function getCountQuery() { /* @var $countQuery Query */ $countQuery = $this->cloneQuery($this->query); if (!$countQuery->hasHint(CountWalker::HINT_DISTINCT)) { $countQuery->setHint(CountWalker::HINT_DISTINCT, true); } if ($this->useOutputWalker($countQuery)) { $platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win $rsm = new ResultSetMapping(); $rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count'); $countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\\ORM\\Tools\\Pagination\\CountOutputWalker'); $countQuery->setResultSetMapping($rsm); } else { $this->appendTreeWalker($countQuery, 'Doctrine\\ORM\\Tools\\Pagination\\CountWalker'); } $countQuery->setFirstResult(null)->setMaxResults(null); $parser = new Parser($countQuery); $parameterMappings = $parser->parse()->getParameterMappings(); /* @var $parameters \Doctrine\Common\Collections\Collection|\Doctrine\ORM\Query\Parameter[] */ $parameters = $countQuery->getParameters(); foreach ($parameters as $key => $parameter) { $parameterName = $parameter->getName(); if (!(isset($parameterMappings[$parameterName]) || array_key_exists($parameterName, $parameterMappings))) { unset($parameters[$key]); } } $countQuery->setParameters($parameters); return $countQuery; }
/** * 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() { $types = array(); foreach ($this->parameters as $parameter) { /** @var Query\Parameter $parameter */ $types[$parameter->getName()] = $parameter->getType(); } // Return previous parser result if the query and the filter collection are both clean if ($this->_state === self::STATE_CLEAN && $this->_parsedTypes === $types && $this->_em->isFiltersStateClean()) { return $this->_parserResult; } $this->_state = self::STATE_CLEAN; $this->_parsedTypes = $types; // Check query cache. if (!($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver()))) { $parser = new Parser($this); $this->_parserResult = $parser->parse(); return $this->_parserResult; } $hash = $this->_getQueryCacheId(); $cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash); if ($cached instanceof ParserResult) { // Cache hit. $this->_parserResult = $cached; return $this->_parserResult; } // Cache miss. $parser = new Parser($this); $this->_parserResult = $parser->parse(); $queryCache->save($hash, $this->_parserResult, $this->_queryCacheTTL); return $this->_parserResult; }
/** * Parses the DQL query, if necessary, and stores the parser result. * * Note: Populates $this->_parserResult as a side-effect. * * @return Doctrine\ORM\Query\ParserResult */ public function parse() { if ($this->_state === self::STATE_DIRTY) { $parser = new Parser($this); $this->_parserResult = $parser->parse(); $this->_state = self::STATE_CLEAN; } return $this->_parserResult; }
/** * @param Query $query * * @return ParserResult */ public static function parseQuery(Query $query) { $parser = new Query\Parser($query); return $parser->parse(); }