diff --git a/lib/Doctrine/ORM/Query/AST/PathExpression.php b/lib/Doctrine/ORM/Query/AST/PathExpression.php
index 076f4400a..4f8d0e277 100644
--- a/lib/Doctrine/ORM/Query/AST/PathExpression.php
+++ b/lib/Doctrine/ORM/Query/AST/PathExpression.php
@@ -59,15 +59,6 @@ class PathExpression extends Node
public function dispatch($walker)
{
- switch ($this->type) {
- case self::TYPE_STATE_FIELD:
- return $walker->walkStateFieldPathExpression($this);
- case self::TYPE_SINGLE_VALUED_ASSOCIATION:
- return $walker->walkSingleValuedAssociationPathExpression($this);
- case self::TYPE_COLLECTION_VALUED_ASSOCIATION:
- return $walker->walkCollectionValuedAssociationPathExpression($this);
- default:
- throw new \Exception("Unexhaustive match.");
- }
+ return $walker->walkPathExpression($this);
}
}
diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php
index 095299943..29fa3f18f 100644
--- a/lib/Doctrine/ORM/Query/Parser.php
+++ b/lib/Doctrine/ORM/Query/Parser.php
@@ -66,12 +66,12 @@ class Parser
);
/**
- * Path expressions that were encountered during parsing of SelectExpressions
+ * Expressions that were encountered during parsing of identifiers and expressions
* and still need to be validated.
*
* @var array
*/
- private $_deferredPathExpressionStacks = array();
+ private $_deferredExpressionsStack = array();
/**
* The lexer.
@@ -485,25 +485,172 @@ class Parser
}
/**
- * Begins a new stack of deferred path expressions.
+ * Subscribe expression to be validated.
+ *
+ * @param mixed $expression
+ * @param string $method
+ * @param array $token
+ * @param integer $nestingLevel
*/
- private function _beginDeferredPathExpressionStack()
+ private function _subscribeExpression($expression, $method, $token, $nextingLevel = null)
{
- $this->_deferredPathExpressionStacks[] = array();
+ $nestingLevel = ($nestingLevel !== null) ?: $this->_nestingLevel;
+
+ $exprStack[] = array(
+ 'method' => $method,
+ 'expression' => $expression,
+ 'nestingLevel' => $nestingLevel,
+ 'token' => $token,
+ );
+
+ array_push($this->_deferredExpressionsStack, $exprStack);
}
/**
* Processes the topmost stack of deferred path expressions.
*/
- private function _processDeferredPathExpressionStack()
+ private function _processDeferredExpressionsStack()
{
- $exprStack = array_pop($this->_deferredPathExpressionStacks);
-
- foreach ($exprStack as $item) {
- $this->_validatePathExpression(
- $item['pathExpression'], $item['nestingLevel'], $item['token']
+ foreach ($this->_deferredExpressionsStack as $item) {
+ $method = '_validate' . $item['method'];
+
+ $this->$method($item['expression'], $item['token'], $item['nestingLevel']);
+ }
+ }
+
+
+ /**
+ * Validates that the given IdentificationVariable is a semantically correct.
+ * It must exist in query components list.
+ *
+ * @param string $identVariable
+ * @param array $token
+ * @param integer $nestingLevel
+ *
+ * @return array Query Component
+ */
+ private function _validateIdentificationVariable($identVariable, $token, $nestingLevel)
+ {
+ // Check if IdentificationVariable exists in queryComponents
+ if ( ! isset($this->_queryComponents[$identVariable])) {
+ $this->semanticalError("'$identVariable' is not defined.", $token);
+ }
+
+ $qComp = $this->_queryComponents[$identVariable];
+
+ // Check if queryComponent points to an AbstractSchemaName or a ResultVariable
+ if ( ! isset($qComp['metadata'])) {
+ $this->semanticalError("'$identVariable' does not point to a Class.", $token);
+ }
+
+ // Validate if identification variable nesting level is lower or equal than the current one
+ if ($qComp['nestingLevel'] > $nestingLevel) {
+ $this->semanticalError(
+ "'$identVariable' is used outside the scope of its declaration.", $token
);
}
+
+ return $qComp;
+ }
+
+ /**
+ * Validates that the given AliasIdentificationVariable is a semantically correct.
+ * It must not exist in query components list.
+ *
+ * @param string $aliasIdentVariable
+ * @param array $token
+ * @param integer $nestingLevel
+ *
+ * @return boolean
+ */
+ private function _validateAliasIdentificationVariable($aliasIdentVariable, $token, $nestingLevel)
+ {
+ $exists = isset($this->_queryComponents[$aliasIdentVariable]);
+
+ if ($exists) {
+ $this->semanticalError("'$aliasIdentVariable' is already defined.", $token);
+ }
+
+ return $exists;
+ }
+
+ /**
+ * Validates that the given AbstractSchemaName is a semantically correct.
+ * It must be defined in the scope of Application.
+ *
+ * @param string $schemaName
+ * @param array $token
+ * @param integer $nestingLevel
+ *
+ * @return boolean
+ */
+ private function _validateAbstractSchemaName($schemaName, $token, $nestingLevel)
+ {
+ $exists = class_exists($schemaName, true);
+
+ if ( ! $exists) {
+ $this->semanticalError("Class '$schemaName' is not defined.", $token);
+ }
+
+ return $exists;
+ }
+
+ /**
+ * Validates that the given AliasIdentificationVariable is a semantically correct.
+ * It must exist in query components list.
+ *
+ * @param string $resultVariable
+ * @param array $token
+ * @param integer $nestingLevel
+ *
+ * @return array Query Component
+ */
+ private function _validateResultVariable($resultVariable, $token, $nestingLevel)
+ {
+ // Check if ResultVariable exists in queryComponents
+ if ( ! isset($this->_queryComponents[$resultVariable])) {
+ $this->semanticalError("'$resultVariable' is not defined.", $token);
+ }
+
+ $qComp = $this->_queryComponents[$resultVariable];
+
+ // Check if queryComponent points to an AbstractSchemaName or a ResultVariable
+ if ( ! isset($qComp['resultVariable'])) {
+ $this->semanticalError("'$identVariable' does not point to a ResultVariable.", $token);
+ }
+
+ // Validate if identification variable nesting level is lower or equal than the current one
+ if ($qComp['nestingLevel'] > $nestingLevel) {
+ $this->semanticalError(
+ "'$resultVariable' is used outside the scope of its declaration.", $token
+ );
+ }
+
+ return $qComp;
+ }
+
+ /**
+ * Validates that the given JoinAssociationPathExpression is a semantically correct.
+ *
+ * @param JoinAssociationPathExpression $pathExpression
+ * @param array $token
+ * @param integer $nestingLevel
+ *
+ * @return array Query Component
+ */
+ private function _validateJoinAssociationPathExpression(AST\JoinAssociationPathExpression $pathExpression, $token, $nestingLevel)
+ {
+ $qComp = $this->_queryComponents[$pathExpression->identificationVariable];;
+
+ // Validating association field (*-to-one or *-to-many)
+ $field = $pathExpression->associationField;
+ $class = $qComp['metadata'];
+
+ if ( ! isset($class->associationMappings[$field])) {
+ $this->semanticalError('Class ' . $class->name . ' has no association named ' . $field);
+ }
+
+ return $qComp;
}
/**
@@ -516,19 +663,16 @@ class Parser
* CollectionValuedPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* CollectionValuedAssociationField
*
* @param PathExpression $pathExpression
- * @param integer $nestingLevel
* @param array $token
+ * @param integer $nestingLevel
+ *
* @return integer
*/
- private function _validatePathExpression(AST\PathExpression $pathExpression, $nestingLevel = null, $token = null)
+ private function _validatePathExpression(AST\PathExpression $pathExpression, $token, $nestingLevel)
{
- $identVariable = $pathExpression->identificationVariable;
- $nestingLevel = ($nestingLevel !== null) ?: $this->_nestingLevel;
- $token = ($token) ?: $this->_lexer->lookahead;
+ $qComp = $this->_queryComponents[$pathExpression->identificationVariable];
- $this->_validateIdentificationVariable($identVariable, $nestingLevel, $token);
-
- $class = $this->_queryComponents[$identVariable]['metadata'];
+ $class = $qComp['metadata'];
$stateField = $collectionField = null;
foreach ($pathExpression->parts as $field) {
@@ -550,7 +694,7 @@ class Parser
// Check if field exists
if ( ! isset($class->associationMappings[$field]) && ! isset($class->fieldMappings[$field])) {
$this->semanticalError(
- 'Class ' . $class->name . ' has no field named ' . $field, $token
+ 'Class ' . $class->name . ' has no field or association named ' . $field, $token
);
}
@@ -597,12 +741,12 @@ class Parser
}
// Build the error message
- $semanticalError = 'Invalid PathExpression.';
+ $semanticalError = 'Invalid PathExpression. ';
if (count($expectedStringTypes) == 1) {
- $semanticalError .= ' Must be a ' . $expectedStringTypes[0] . '.';
+ $semanticalError .= 'Must be a ' . $expectedStringTypes[0] . '.';
} else {
- $semanticalError .= ' ' . implode(' or ', $expectedStringTypes) . ' expected.';
+ $semanticalError .= implode(' or ', $expectedStringTypes) . ' expected.';
}
$this->semanticalError($semanticalError, $token);
@@ -613,35 +757,6 @@ class Parser
return $expressionType;
}
-
- /**
- * Validates that the given IdentificationVariable is a semantically correct.
- * It must exist in query components list.
- *
- * @param string $identVariable
- * @param integer $nestingLevel
- * @param array $token
- * @return array Query Component
- */
- private function _validateIdentificationVariable($identVariable, $nestingLevel = null, $token = null)
- {
- $nestingLevel = ($nestingLevel !== null) ?: $this->_nestingLevel;
- $token = ($token) ?: $this->_lexer->lookahead;
-
- if ( ! isset($this->_queryComponents[$identVariable])) {
- $this->semanticalError("'$identVariable' is not defined", $token);
- }
-
- // Validate if identification variable nesting level is lower or equal than the current one
- if ($this->_queryComponents[$identVariable]['nestingLevel'] > $nestingLevel) {
- $this->semanticalError(
- "'$idVariable' is used outside the scope of its declaration",
- $token
- );
- }
-
- return $this->_queryComponents[$identVariable];
- }
/**
@@ -679,15 +794,8 @@ class Parser
*/
public function SelectStatement()
{
- // We need to prevent semantical checks on SelectClause,
- // since we do not have any IdentificationVariable yet
- $this->_beginDeferredPathExpressionStack();
-
$selectStatement = new AST\SelectStatement($this->SelectClause(), $this->FromClause());
- // Activate semantical checks after this point. Process all deferred checks in pipeline
- $this->_processDeferredPathExpressionStack();
-
$selectStatement->whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE)
? $this->WhereClause() : null;
@@ -700,6 +808,9 @@ class Parser
$selectStatement->orderByClause = $this->_lexer->isNextToken(Lexer::T_ORDER)
? $this->OrderByClause() : null;
+ // Activate semantical checks after this point. Process all deferred checks in pipeline
+ $this->_processDeferredExpressionsStack();
+
return $selectStatement;
}
@@ -713,6 +824,9 @@ class Parser
$updateStatement = new AST\UpdateStatement($this->UpdateClause());
$updateStatement->whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE)
? $this->WhereClause() : null;
+
+ // Activate semantical checks after this point. Process all deferred checks in pipeline
+ $this->_processDeferredExpressionsStack();
return $updateStatement;
}
@@ -727,6 +841,9 @@ class Parser
$deleteStatement = new AST\DeleteStatement($this->DeleteClause());
$deleteStatement->whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE)
? $this->WhereClause() : null;
+
+ // Activate semantical checks after this point. Process all deferred checks in pipeline
+ $this->_processDeferredExpressionsStack();
return $deleteStatement;
}
@@ -741,7 +858,19 @@ class Parser
{
$this->match(Lexer::T_IDENTIFIER);
- return $this->_lexer->token['value'];
+ $identVariable = $this->_lexer->token['value'];
+
+ // Defer IdentificationVariable validation
+ $exprStack = array(
+ 'method' => 'IdentificationVariable',
+ 'expression' => $identVariable,
+ 'nestingLevel' => $this->_nestingLevel,
+ 'token' => $this->_lexer->token,
+ );
+
+ array_push($this->_deferredExpressionsStack, $exprStack);
+
+ return $identVariable;
}
/**
@@ -752,8 +881,15 @@ class Parser
public function AliasIdentificationVariable()
{
$this->match(Lexer::T_IDENTIFIER);
+
+ $aliasIdentVariable = $this->_lexer->token['value'];
+
+ // Apply AliasIdentificationVariable validation
+ $this->_validateAliasIdentificationVariable(
+ $aliasIdentVariable, $this->_lexer->token, $this->_nestingLevel
+ );
- return $this->_lexer->token['value'];
+ return $aliasIdentVariable;
}
/**
@@ -765,7 +901,14 @@ class Parser
{
$this->match(Lexer::T_IDENTIFIER);
- return $this->_lexer->token['value'];
+ $schemaName = $this->_lexer->token['value'];
+
+ // Apply AbstractSchemaName validation
+ $this->_validateAbstractSchemaName(
+ $schemaName, $this->_lexer->token, $this->_nestingLevel
+ );
+
+ return $schemaName;
}
/**
@@ -777,7 +920,19 @@ class Parser
{
$this->match(Lexer::T_IDENTIFIER);
- return $this->_lexer->token['value'];
+ $resultVariable = $this->_lexer->token['value'];
+
+ // Defer ResultVariable validation
+ $exprStack = array(
+ 'method' => 'ResultVariable',
+ 'expression' => $resultVariable,
+ 'nestingLevel' => $this->_nestingLevel,
+ 'token' => $this->_lexer->token,
+ );
+
+ array_push($this->_deferredExpressionsStack, $exprStack);
+
+ return $resultVariable;
}
@@ -789,34 +944,37 @@ class Parser
public function JoinAssociationPathExpression()
{
$token = $this->_lexer->lookahead;
+
$identVariable = $this->IdentificationVariable();
$this->match(Lexer::T_DOT);
$this->match(Lexer::T_IDENTIFIER);
$field = $this->_lexer->token['value'];
- // Validating IdentificationVariable (it was already defined previously)
- $this->_validateIdentificationVariable($identVariable, null, $token);
+ $pathExpr = new AST\JoinAssociationPathExpression($identVariable, $field);
- // Validating association field (*-to-one or *-to-many)
- $class = $this->_queryComponents[$identVariable]['metadata'];
+ // Defer JoinAssociationPathExpression validation
+ $exprStack = array(
+ 'method' => 'JoinAssociationPathExpression',
+ 'expression' => $pathExpr,
+ 'nestingLevel' => $this->_nestingLevel,
+ 'token' => $token,
+ );
+
+ array_push($this->_deferredExpressionsStack, $exprStack);
- if ( ! isset($class->associationMappings[$field])) {
- $this->semanticalError('Class ' . $class->name . ' has no field named ' . $field);
- }
-
- return new AST\JoinAssociationPathExpression($identVariable, $field);
+ return $pathExpr;
}
/**
- * Parses an arbitrary path expression. Applies or defer semantical validation
+ * Parses an arbitrary path expression and defers semantical validation
* based on expected types.
*
* PathExpression ::= IdentificationVariable "." {identifier "."}* identifier
*
- * @param integer $expectedType
+ * @param integer $expectedTypes
* @return \Doctrine\ORM\Query\AST\PathExpression
*/
- public function PathExpression($expectedType)
+ public function PathExpression($expectedTypes)
{
$token = $this->_lexer->lookahead;
$identVariable = $this->IdentificationVariable();
@@ -830,24 +988,18 @@ class Parser
} while ($this->_lexer->isNextToken(Lexer::T_DOT));
// Creating AST node
- $pathExpr = new AST\PathExpression($expectedType, $identVariable, $parts);
+ $pathExpr = new AST\PathExpression($expectedTypes, $identVariable, $parts);
// Defer PathExpression validation if requested to be defered
- if ( ! empty($this->_deferredPathExpressionStacks)) {
- $exprStack = array_pop($this->_deferredPathExpressionStacks);
- $exprStack[] = array(
- 'pathExpression' => $pathExpr,
- 'nestingLevel' => $this->_nestingLevel,
- 'token' => $token,
- );
- array_push($this->_deferredPathExpressionStacks, $exprStack);
-
- return $pathExpr;
- }
-
- // Apply PathExpression validation normally (not in defer mode)
- $this->_validatePathExpression($pathExpr, $this->_nestingLevel, $token);
+ $exprStack = array(
+ 'method' => 'PathExpression',
+ 'expression' => $pathExpr,
+ 'nestingLevel' => $this->_nestingLevel,
+ 'token' => $token,
+ );
+ array_push($this->_deferredExpressionsStack, $exprStack);
+
return $pathExpr;
}
@@ -975,7 +1127,7 @@ class Parser
}
/**
- * UpdateClause ::= "UPDATE" AbstractSchemaName [["AS"] AliasIdentificationVariable] "SET" UpdateItem {"," UpdateItem}*
+ * UpdateClause ::= "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}*
*
* @return \Doctrine\ORM\Query\AST\UpdateClause
*/
@@ -984,18 +1136,12 @@ class Parser
$this->match(Lexer::T_UPDATE);
$token = $this->_lexer->lookahead;
$abstractSchemaName = $this->AbstractSchemaName();
- $aliasIdentificationVariable = null;
-
+
if ($this->_lexer->isNextToken(Lexer::T_AS)) {
$this->match(Lexer::T_AS);
}
- if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
- $token = $this->_lexer->lookahead;
- $aliasIdentificationVariable = $this->AliasIdentificationVariable();
- } else {
- $aliasIdentificationVariable = $abstractSchemaName;
- }
+ $aliasIdentificationVariable = $this->AliasIdentificationVariable();
$class = $this->_em->getClassMetadata($abstractSchemaName);
@@ -1011,6 +1157,7 @@ class Parser
$this->_queryComponents[$aliasIdentificationVariable] = $queryComponent;
$this->match(Lexer::T_SET);
+
$updateItems = array();
$updateItems[] = $this->UpdateItem();
@@ -1026,7 +1173,7 @@ class Parser
}
/**
- * DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName [["AS"] AliasIdentificationVariable]
+ * DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable
*
* @return \Doctrine\ORM\Query\AST\DeleteClause
*/
@@ -1040,18 +1187,12 @@ class Parser
$token = $this->_lexer->lookahead;
$deleteClause = new AST\DeleteClause($this->AbstractSchemaName());
- $aliasIdentificationVariable = null;
-
+
if ($this->_lexer->isNextToken(Lexer::T_AS)) {
$this->match(Lexer::T_AS);
}
- if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
- $token = $this->_lexer->lookahead;
- $aliasIdentificationVariable = $this->AliasIdentificationVariable();
- } else {
- $aliasIdentificationVariable = $deleteClause->abstractSchemaName;
- }
+ $aliasIdentificationVariable = $this->AliasIdentificationVariable();
$deleteClause->aliasIdentificationVariable = $aliasIdentificationVariable;
$class = $this->_em->getClassMetadata($deleteClause->abstractSchemaName);
@@ -1183,12 +1324,8 @@ class Parser
// Increase query nesting level
$this->_nestingLevel++;
- $this->_beginDeferredPathExpressionStack();
-
$subselect = new AST\Subselect($this->SimpleSelectClause(), $this->SubselectFromClause());
- $this->_processDeferredPathExpressionStack();
-
$subselect->whereClause = $this->_lexer->isNextToken(Lexer::T_WHERE)
? $this->WhereClause() : null;
@@ -1216,17 +1353,14 @@ class Parser
public function UpdateItem()
{
$token = $this->_lexer->lookahead;
+
$identVariable = $this->IdentificationVariable();
-
- // Validate if IdentificationVariable is defined
- $queryComponent = $this->_validateIdentificationVariable($identVariable, null, $token);
-
$this->match(Lexer::T_DOT);
$this->match(Lexer::T_IDENTIFIER);
$field = $this->_lexer->token['value'];
// Check if field exists
- $class = $queryComponent['metadata'];
+ $class = $this->_queryComponents[$identVariable]['metadata'];
if ( ! isset($class->associationMappings[$field]) && ! isset($class->fieldMappings[$field])) {
$this->semanticalError(
@@ -1285,17 +1419,6 @@ class Parser
if ($glimpse['value'] != '.') {
$token = $this->_lexer->lookahead;
$expr = $this->ResultVariable();
-
- // Check if ResultVariable is defined in query components
- $queryComponent = $this->_validateIdentificationVariable($expr, null, $token);
-
- // Outer defininition used in inner subselect is not enough.
- // ResultVariable exists in queryComponents, check nesting level
- if ($queryComponent['nestingLevel'] != $this->_nestingLevel) {
- $this->semanticalError(
- "'$expr' is used outside the scope of its declaration"
- );
- }
} else {
$expr = $this->StateFieldPathExpression();
}
@@ -1564,7 +1687,7 @@ class Parser
// Include ResultVariable in query components.
$this->_queryComponents[$fieldAliasIdentificationVariable] = array(
- 'resultvariable' => $expression,
+ 'resultVariable' => $expression,
'nestingLevel' => $this->_nestingLevel,
'token' => $token,
);
diff --git a/lib/Doctrine/ORM/Query/QueryException.php b/lib/Doctrine/ORM/Query/QueryException.php
index 22753e228..414492bb4 100644
--- a/lib/Doctrine/ORM/Query/QueryException.php
+++ b/lib/Doctrine/ORM/Query/QueryException.php
@@ -21,6 +21,8 @@
namespace Doctrine\ORM\Query;
+use Doctrine\ORM\Query\AST\PathExpression;
+
/**
* Description of QueryException
*
@@ -63,6 +65,14 @@ class QueryException extends \Doctrine\Common\DoctrineException
{
return new self("Invalid parameter: token ".$key." is not defined in the query.");
}
+
+ public static function invalidPathExpression($pathExpr)
+ {
+ return new self(
+ "Invalid PathExpression '" . $pathExpr->identificationVariable .
+ "." . implode('.', $pathExpr->parts) . "'."
+ );
+ }
/**
* @param Doctrine\ORM\Mapping\AssociationMapping $assoc
diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php
index 418efd875..83400e5ad 100644
--- a/lib/Doctrine/ORM/Query/SqlWalker.php
+++ b/lib/Doctrine/ORM/Query/SqlWalker.php
@@ -22,6 +22,7 @@
namespace Doctrine\ORM\Query;
use Doctrine\ORM\Query,
+ Doctrine\ORM\Query\QueryException,
Doctrine\Common\DoctrineException;
/**
@@ -425,12 +426,35 @@ class SqlWalker implements TreeWalker
$sql .= $class->getQuotedColumnName($fieldName, $this->_platform);
break;
+
+ case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION:
+ // "u.Group" should be converted to:
+ // 1- IdentificationVariable is the owning side:
+ // Just append the condition: u.group_id = ?
+ /*$parts = $pathExpr->parts;
+ $numParts = count($parts);
+ $dqlAlias = $pathExpr->identificationVariable;
+ $fieldName = $parts[$numParts - 1];
+ $qComp = $this->_queryComponents[$dqlAlias];
+ $class = $qComp['metadata'];
+ $assoc = $class->associationMappings[$fieldName];
+
+ if ($assoc->isOwningSide) {
+ foreach ($assoc->)
+ $sql .= $this->walkIdentificationVariable($dqlAlias, $fieldName) . '.';
+
+ }
+
+ // 2- IdentificationVariable is the inverse side:
+ // Join required: INNER JOIN u.Group g
+ // Append condition: g.id = ?
+ break;*/
case AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION:
throw DoctrineException::notImplemented();
default:
- throw DoctrineException::invalidPathExpression($pathExpr->type);
+ throw QueryException::invalidPathExpression($pathExpr);
}
return $sql;
diff --git a/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php
index 1f50d7d7a..8d1597629 100644
--- a/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php
+++ b/tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php
@@ -52,10 +52,6 @@ class DeleteSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
$query->free();
} catch (\Exception $e) {
- if ($debug) {
- echo $e->getTraceAsString() . PHP_EOL;
- }
-
$this->fail($e->getMessage());
}
}
diff --git a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php
index 82cfe9a86..c0810d236 100644
--- a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php
+++ b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php
@@ -1,7 +1,8 @@
parseDql($dql);
- } catch (\Exception $e) {
+ } catch (QueryException $e) {
if ($debug) {
echo $e->getTraceAsString() . PHP_EOL;
}
@@ -31,8 +32,9 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
{
try {
$parserResult = $this->parseDql($dql);
+
$this->fail('No syntax errors were detected, when syntax errors were expected');
- } catch (\Exception $e) {
+ } catch (QueryException $e) {
if ($debug) {
echo $e->getMessage() . PHP_EOL;
echo $e->getTraceAsString() . PHP_EOL;
@@ -248,6 +250,16 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
$this->assertValidDql("SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name LIKE 'z|%' ESCAPE '|'");
}
+ public function testFieldComparisonWithoutAlias()
+ {
+ $this->assertInvalidDql("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE id = 1");
+ }
+
+ public function testDuplicatedAliasDeclaration()
+ {
+ $this->assertInvalidDql("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u INNER JOIN u.articles u WHERE u.id = 1");
+ }
+
/*public function testImplicitJoinInWhereOnSingleValuedAssociationPathExpression()
{
// This should be allowed because avatar is a single-value association.
@@ -288,7 +300,7 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
public function testDeleteAll()
{
- $this->assertValidDql('DELETE FROM Doctrine\Tests\Models\CMS\CmsUser');
+ $this->assertValidDql('DELETE FROM Doctrine\Tests\Models\CMS\CmsUser u');
}
public function testDeleteWithCondition()
diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
index 7c6924d59..369183914 100644
--- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
+++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
@@ -464,16 +464,17 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
}
- /* Not yet implemented, needs more thought
+ /* Not yet implemented, needs more thought */
public function testSingleValuedAssociationFieldInWhere()
{
- $this->assertSqlGeneration(
+ /*$this->assertSqlGeneration(
"SELECT p FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.user = ?1",
- "SELECT c0_.phonenumber AS phonenumber0 FROM cms_phonenumbers c0_ WHERE c0_.user_id = ?"
+ "SELECT c0_.id AS id0, c0_user_id AS user_id1, c0_.phonenumber AS phonenumber2 FROM cms_phonenumbers c0_ WHERE c0_.user_id = ?"
);
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.address = ?1",
- "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id = (SELECT c1_.user_id FROM cms_addresses c1_ WHERE c1_.id = ?)"
- );
- }*/
+ //"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id = (SELECT c1_.user_id FROM cms_addresses c1_ WHERE c1_.id = ?)"
+ "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_addresses c1_ WHERE c1_.user_id = c0_.id AND c1_.id = ?)"
+ );*/
+ }
}