/** * @param Query $query * @param array $paramMappings * @return array * @throws \Doctrine\ORM\Query\QueryException */ protected function processParameterMappings(Query $query, $paramMappings) { $sqlParams = array(); $types = array(); /** @var Parameter $parameter */ foreach ($query->getParameters() as $parameter) { $key = $parameter->getName(); if (!isset($paramMappings[$key])) { throw QueryException::unknownParameter($key); } $value = $query->processParameterValue($parameter->getValue()); $type = $parameter->getValue() === $value ? $parameter->getType() : Query\ParameterTypeInferer::inferType($value); foreach ($paramMappings[$key] as $position) { $types[$position] = $type; } $sqlPositions = $paramMappings[$key]; $value = array($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); }
/** * @expectedException Psc\Doctrine\QueryException */ public function testwithException_throwsPscDoctrineQueryException() { $query = $this->doublesManager->createQueryMock(array('getResult', 'getScalarResult', 'getDQL'), $this->emm); $query->expects($this->once())->method('getDQL')->will($this->returnValue('SELECT * FROM DAM\\AGE')); $query->expects($this->once())->method('getResult')->will($this->throwException(\Doctrine\ORM\Query\QueryException::semanticalError('DAM\\AGE ist keine Tabelle natürlich'))); $this->runDeliverQuery(NULL, 'result', $query); }
/** * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker * @return string * @throws QueryException */ public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) { $unit = strtoupper(is_string($this->unit) ? $this->unit : $this->unit->value); if (!in_array($unit, self::$allowedUnits)) { throw QueryException::semanticalError('DATE_SUB() does not support unit "' . $unit . '".'); } return 'DATE_SUB(' . $this->firstDateExpression->dispatch($sqlWalker) . ', INTERVAL ' . $this->intervalExpression->dispatch($sqlWalker) . ' ' . $unit . ')'; }
/** * Create platform function node. * * @param string $platformName * @param string $functionName * @param array $parameters * @throws \Doctrine\ORM\Query\QueryException * @return PlatformFunctionNode */ public static function create($platformName, $functionName, array $parameters) { $className = __NAMESPACE__ . '\\Platform\\Functions\\' . Inflector::classify(strtolower($platformName)) . '\\' . Inflector::classify(strtolower($functionName)); if (!class_exists($className)) { throw QueryException::syntaxError(sprintf('Function "%s" does not supported for platform "%s"', $functionName, $platformName)); } return new $className($parameters); }
/** * @param string $value * * @throws \Doctrine\ORM\Query\QueryException */ public function __construct($value) { if (strlen($value) == 1) { throw \Doctrine\ORM\Query\QueryException::invalidParameterFormat($value); } $param = substr($value, 1); $this->isNamed = !is_numeric($param); $this->name = $param; }
/** * @override */ public function getSql(SqlWalker $sqlWalker) { switch (strtolower($this->unit->value)) { case 'day': return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddDaysExpression($this->firstDateExpression->dispatch($sqlWalker), $this->intervalExpression->dispatch($sqlWalker)); case 'month': return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression($this->firstDateExpression->dispatch($sqlWalker), $this->intervalExpression->dispatch($sqlWalker)); default: throw QueryException::semanticalError('DATE_ADD() only supports units of type day and month.'); } }
public function getSql(SqlWalker $sqlWalker) { $unit = strtolower($this->unit); if ($unit == "day") { return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddDaysExpression($this->firstDateExpression->dispatch($sqlWalker), $this->intervalExpression->dispatch($sqlWalker)); } else { if ($unit == "month") { return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression($this->firstDateExpression->dispatch($sqlWalker), $this->intervalExpression->dispatch($sqlWalker)); } else { throw QueryException::semanticalError('DATE_ADD() only supports units of type day and month.'); } } }
/** * @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]; }
/** * Generates a new syntax error. * * @param string $expected Expected string. * @param array $token Got token. * * @throws \Doctrine\ORM\Query\QueryException */ public function syntaxError($expected = '', $token = null) { if ($token === null) { $token = $this->_lexer->lookahead; } $tokenPos = isset($token['position']) ? $token['position'] : '-1'; $message = "line 0, col {$tokenPos}: Error: "; if ($expected !== '') { $message .= "Expected {$expected}, got "; } else { $message .= 'Unexpected '; } if ($this->_lexer->lookahead === null) { $message .= 'end of string.'; } else { $message .= "'{$token['value']}'"; } throw QueryException::syntaxError($message); }
/** * Executes the query. * * @param string $params Any additional query parameters. * @param integer $hydrationMode Processing mode to be used during the hydration process. * @return mixed */ public function execute($params = array(), $hydrationMode = null) { // If there are still pending insertions in the UnitOfWork we need to flush // in order to guarantee a correct result. if ($this->_em->getUnitOfWork()->hasPendingInsertions()) { $this->_em->flush(); } if ($hydrationMode !== null) { $this->_hydrationMode = $hydrationMode; } $params = $this->getParameters($params); if (isset($params[0])) { throw QueryException::invalidParameterPosition(0); } // Check result cache if ($this->_useResultCache && ($cacheDriver = $this->getResultCacheDriver())) { $id = $this->getResultCacheId($params); $cached = $this->_expireResultCache ? false : $cacheDriver->fetch($id); if ($cached === false) { // Cache miss. $stmt = $this->_doExecute($params); $result = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll($stmt, $this->_resultSetMapping, $this->_hints); $cacheDriver->save($id, $result, $this->_resultCacheTTL); return $result; } else { // Cache hit. return $cached; } } $stmt = $this->_doExecute($params); if (is_numeric($stmt)) { return $stmt; } return $this->_em->getHydrator($this->_hydrationMode)->hydrateAll($stmt, $this->_resultSetMapping, $this->_hints); }
/** * {@inheritdoc} */ protected function _doExecute() { $executor = $this->_parse()->getSqlExecutor(); // Prepare parameters $paramMappings = $this->_parserResult->getParameterMappings(); if (count($paramMappings) != count($this->_params)) { throw QueryException::invalidParameterNumber(); } $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]; } } if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) { if ($this->_em->getUnitOfWork()->getEntityState($value) == UnitOfWork::STATE_MANAGED) { $idValues = $this->_em->getUnitOfWork()->getEntityIdentifier($value); } else { $class = $this->_em->getClassMetadata(get_class($value)); $idValues = $class->getIdentifierValues($value); } $sqlPositions = $paramMappings[$key]; $cSqlPos = count($sqlPositions); $cIdValues = count($idValues); $idValues = array_values($idValues); for ($i = 0; $i < $cSqlPos; $i++) { $sqlParams[$sqlPositions[$i]] = $idValues[$i % $cIdValues]; } } else { foreach ($paramMappings[$key] as $position) { $sqlParams[$position] = $value; } } } if ($sqlParams) { ksort($sqlParams); $sqlParams = array_values($sqlParams); } 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 ($sqlParams) { ksort($sqlParams); $sqlParams = array_values($sqlParams); } return array($sqlParams, $types); }
/** * Generates a new semantical error. * * @param string $message Optional message. * @param array|null $token Optional token. * * @return void * * @throws \Doctrine\ORM\Query\QueryException */ public function semanticalError($message = '', $token = null) { if ($token === null) { $token = $this->lexer->lookahead; } // Minimum exposed chars ahead of token $distance = 12; // Find a position of a final word to display in error string $dql = $this->query->getDql(); $length = strlen($dql); $pos = $token['position'] + $distance; $pos = strpos($dql, ' ', $length > $pos ? $pos : $length); $length = $pos !== false ? $pos - $token['position'] : $distance; $tokenPos = isset($token['position']) && $token['position'] > 0 ? $token['position'] : '-1'; $tokenStr = substr($dql, $token['position'], $length); // Building informative message $message = 'line 0, col ' . $tokenPos . " near '" . $tokenStr . "': Error: " . $message; throw QueryException::semanticalError($message, QueryException::dqlError($this->query->getDQL())); }
/** * {@inheritdoc} */ public function walkLiteral($literal) { switch ($literal->type) { case AST\Literal::STRING: return $this->conn->quote($literal->value); case AST\Literal::BOOLEAN: $bool = strtolower($literal->value) == 'true' ? true : false; $boolVal = $this->conn->getDatabasePlatform()->convertBooleans($bool); return $boolVal; case AST\Literal::NUMERIC: return $literal->value; default: throw QueryException::invalidLiteral($literal); } }
/** * Executes the query. * * @param array $params Any additional query parameters. * @param integer $hydrationMode Processing mode to be used during the hydration process. * @return mixed */ public function execute($params = array(), $hydrationMode = null) { if ($hydrationMode !== null) { $this->setHydrationMode($hydrationMode); } if ($params) { $this->setParameters($params); } if (isset($this->_params[0])) { throw QueryException::invalidParameterPosition(0); } // Check result cache if ($this->_useResultCache && ($cacheDriver = $this->getResultCacheDriver())) { list($key, $hash) = $this->getResultCacheId(); $cached = $this->_expireResultCache ? false : $cacheDriver->fetch($hash); if ($cached === false || !isset($cached[$key])) { // Cache miss. $stmt = $this->_doExecute(); $result = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll($stmt, $this->_resultSetMapping, $this->_hints); $cacheDriver->save($hash, array($key => $result), $this->_resultCacheTTL); return $result; } else { // Cache hit. return $cached[$key]; } } $stmt = $this->_doExecute(); if (is_numeric($stmt)) { return $stmt; } return $this->_em->getHydrator($this->_hydrationMode)->hydrateAll($stmt, $this->_resultSetMapping, $this->_hints); }
/** * Generates a new semantical error. * * @param string $message Optional message. * @param array $token Optional token. * * @throws \Doctrine\ORM\Query\QueryException */ public function semanticalError($message = '', $token = null) { if ($token === null) { $token = $this->_lexer->lookahead; } // Minimum exposed chars ahead of token $distance = 12; // Find a position of a final word to display in error string $dql = $this->_query->getDql(); $length = strlen($dql); $pos = $token['position'] + $distance; $pos = strpos($dql, ' ', ($length > $pos) ? $pos : $length); $length = ($pos !== false) ? $pos - $token['position'] : $distance; // Building informative message $message = 'line 0, col ' . ( (isset($token['position']) && $token['position'] > 0) ? $token['position'] : '-1' ) . " near '" . substr($dql, $token['position'], $length) . "': Error: " . $message; throw \Doctrine\ORM\Query\QueryException::semanticalError($message); }
/** * {@inheritdoc} * * @override */ protected function _prepareParams(array $params) { $sqlParams = array(); $paramMappings = $this->_parserResult->getParameterMappings(); if (count($paramMappings) != count($params)) { throw QueryException::invalidParameterNumber(); } foreach ($params as $key => $value) { if (!isset($paramMappings[$key])) { throw QueryException::unknownParameter($key); } if (is_object($value)) { //$values = $this->_em->getClassMetadata(get_class($value))->getIdentifierValues($value); $values = $this->_em->getUnitOfWork()->getEntityIdentifier($value); //var_dump($this->_em->getUnitOfWork()->getEntityIdentifier($value)); $sqlPositions = $paramMappings[$key]; $sqlParams = array_merge($sqlParams, array_combine((array) $sqlPositions, $values)); } else { if (is_bool($value)) { $boolValue = $this->_em->getConnection()->getDatabasePlatform()->convertBooleans($value); foreach ($paramMappings[$key] as $position) { $sqlParams[$position] = $boolValue; } } else { foreach ($paramMappings[$key] as $position) { $sqlParams[$position] = $value; } } } } ksort($sqlParams); return array_values($sqlParams); }
/** * Infer field type to be used by parameter type casting. * * @param string $field * @param mixed $value * @return integer */ private function getType($field, $value) { switch (true) { case isset($this->_class->fieldMappings[$field]): $type = Type::getType($this->_class->fieldMappings[$field]['type'])->getBindingType(); break; case isset($this->_class->associationMappings[$field]): $assoc = $this->_class->associationMappings[$field]; if (count($assoc['sourceToTargetKeyColumns']) > 1) { throw Query\QueryException::associationPathCompositeKeyNotSupported(); } $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']); $targetColumn = $assoc['joinColumns'][0]['referencedColumnName']; $type = null; if (isset($targetClass->fieldNames[$targetColumn])) { $type = Type::getType($targetClass->fieldMappings[$targetClass->fieldNames[$targetColumn]]['type'])->getBindingType(); } break; default: $type = null; } if (is_array($value)) { $type += Connection::ARRAY_PARAM_OFFSET; } return $type; }
/** * {@inheritdoc} */ protected function _doExecute() { $executor = $this->_parse()->getSqlExecutor(); // Prepare parameters $paramMappings = $this->_parserResult->getParameterMappings(); if (count($paramMappings) != count($this->_params)) { throw QueryException::invalidParameterNumber(); } $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]; } } if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) { $values = $this->_em->getUnitOfWork()->getEntityIdentifier($value); $sqlPositions = $paramMappings[$key]; $sqlParams = array_merge($sqlParams, array_combine((array) $sqlPositions, $values)); } else { foreach ($paramMappings[$key] as $position) { $sqlParams[$position] = $value; } } } if ($sqlParams) { ksort($sqlParams); $sqlParams = array_values($sqlParams); } if ($this->_resultSetMapping === null) { $this->_resultSetMapping = $this->_parserResult->getResultSetMapping(); } return $executor->execute($this->_em->getConnection(), $sqlParams, $types); }
/** * Add query components which will add to query hints * * @param array $queryComponents * @throws QueryException */ protected function addQueryComponents(array $queryComponents) { $requiredKeys = array('metadata', 'parent', 'relation', 'map', 'nestingLevel', 'token'); foreach ($queryComponents as $dqlAlias => $queryComponent) { if (array_diff($requiredKeys, array_keys($queryComponent))) { throw QueryException::invalidQueryComponent($dqlAlias); } $this->queryComponents[$dqlAlias] = $queryComponent; } }
/** * Processes query parameter mappings. * * @param array $paramMappings * * @return array * * @throws Query\QueryException */ private function processParameterMappings($paramMappings) { $sqlParams = array(); $types = array(); foreach ($this->parameters as $parameter) { $key = $parameter->getName(); $value = $parameter->getValue(); if (!isset($paramMappings[$key])) { throw QueryException::unknownParameter($key); } if (isset($this->_resultSetMapping->metadataParameterMapping[$key]) && $value instanceof ClassMetadata) { $value = $value->getMetadataValue($this->_resultSetMapping->metadataParameterMapping[$key]); } $value = $this->processParameterValue($value); $type = $parameter->getValue() === $value ? $parameter->getType() : 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 = array($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 array($sqlParams, $types); }
/** * Executes the query. * * @param string $params Any additional query parameters. * @param integer $hydrationMode Processing mode to be used during the hydration process. * @return mixed */ public function execute($params = array(), $hydrationMode = null) { // If there are still pending insertions in the UnitOfWork we need to flush // in order to guarantee a correct result. //TODO: Think this over. Its tricky. Not doing this can lead to strange results // potentially, but doing it could result in endless loops when querying during // a flush, i.e. inside an event listener. if ($this->_em->getUnitOfWork()->hasPendingInsertions()) { $this->_em->flush(); } if ($hydrationMode !== null) { $this->setHydrationMode($hydrationMode); } if ($params) { $this->setParameters($params); } if (isset($this->_params[0])) { throw QueryException::invalidParameterPosition(0); } // Check result cache if ($this->_useResultCache && ($cacheDriver = $this->getResultCacheDriver())) { $id = $this->_getResultCacheId(); $cached = $this->_expireResultCache ? false : $cacheDriver->fetch($id); if ($cached === false) { // Cache miss. $stmt = $this->_doExecute(); $result = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll($stmt, $this->_resultSetMapping, $this->_hints); $cacheDriver->save($id, $result, $this->_resultCacheTTL); return $result; } else { // Cache hit. return $cached; } } $stmt = $this->_doExecute(); if (is_numeric($stmt)) { return $stmt; } return $this->_em->getHydrator($this->_hydrationMode)->hydrateAll($stmt, $this->_resultSetMapping, $this->_hints); }
/** * 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]; // optimized multi value sql positions away for now, // they are not allowed in DQL anyways. $value = array($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); }
/** * UpdateItem ::= [IdentificationVariable "."] {StateField | SingleValuedAssociationField} "=" NewValue */ public function _UpdateItem() { $peek = $this->_lexer->glimpse(); $identVariable = null; if ($peek['value'] == '.') { $this->match(Lexer::T_IDENTIFIER); $identVariable = $this->_lexer->token['value']; $this->match('.'); } else { throw QueryException::missingAliasQualifier(); } $this->match(Lexer::T_IDENTIFIER); $field = $this->_lexer->token['value']; $this->match('='); $newValue = $this->_NewValue(); $updateItem = new AST\UpdateItem($field, $newValue); $updateItem->setIdentificationVariable($identVariable); return $updateItem; }