Commit b2b06554 authored by guilhermeblanco's avatar guilhermeblanco

[2.0] More work on DQL parser of Doctrine 2.0. More semantical checks...

[2.0] More work on DQL parser of Doctrine 2.0. More semantical checks included. Missing scope checking of ResultVariable (SELECT and Sub-SELECT differences). Removed invalid grammar rules.
parent e1f2b8ab
...@@ -323,6 +323,9 @@ class Parser ...@@ -323,6 +323,9 @@ class Parser
/** /**
* Peeks beyond the specified token and returns the first token after that one. * Peeks beyond the specified token and returns the first token after that one.
*
* @param array $token
* @return array
*/ */
private function _peekBeyond($token) private function _peekBeyond($token)
{ {
...@@ -439,8 +442,8 @@ class Parser ...@@ -439,8 +442,8 @@ class Parser
{ {
$exprStack = array_pop($this->_deferredPathExpressionStacks); $exprStack = array_pop($this->_deferredPathExpressionStacks);
foreach ($exprStack as $expr) { foreach ($exprStack as $pathExpression) {
$this->_validatePathExpression($expr); $this->_validatePathExpression($pathExpression);
} }
} }
...@@ -712,7 +715,7 @@ class Parser ...@@ -712,7 +715,7 @@ class Parser
* PathExpression ::= IdentificationVariable "." {identifier "."}* identifier * PathExpression ::= IdentificationVariable "." {identifier "."}* identifier
* *
* @param integer $expectedType * @param integer $expectedType
* @return PathExpression * @return AST\PathExpression
*/ */
public function PathExpression($expectedType) public function PathExpression($expectedType)
{ {
...@@ -792,12 +795,20 @@ class Parser ...@@ -792,12 +795,20 @@ class Parser
/** /**
* SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField * SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField
*
* @todo We should only allow 1 single part here (state field). It is used by INDEX BY clause.
*/ */
public function SimpleStateFieldPathExpression() public function SimpleStateFieldPathExpression()
{ {
return $this->PathExpression(AST\PathExpression::TYPE_STATE_FIELD); $pathExpression = $this->PathExpression(AST\PathExpression::TYPE_STATE_FIELD);
$parts = $pathExpression->getParts();
if (count($parts) > 1) {
$this->semanticalError(
"Invalid SimpleStateFieldPathExpression. " .
"Expected state field, got association '{$parts[0]}'."
);
}
return $pathExpression;
} }
...@@ -860,8 +871,7 @@ class Parser ...@@ -860,8 +871,7 @@ class Parser
} }
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) { if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$this->match(Lexer::T_IDENTIFIER); $aliasIdentificationVariable = $this->AliasIdentificationVariable();
$aliasIdentificationVariable = $this->_lexer->token['value'];
} else { } else {
$aliasIdentificationVariable = $abstractSchemaName; $aliasIdentificationVariable = $abstractSchemaName;
} }
...@@ -910,15 +920,17 @@ class Parser ...@@ -910,15 +920,17 @@ class Parser
} }
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) { if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$this->match(Lexer::T_IDENTIFIER); $deleteClause->setAliasIdentificationVariable($this->AliasIdentificationVariable());
$deleteClause->setAliasIdentificationVariable($this->_lexer->token['value']);
} else { } else {
$deleteClause->setAliasIdentificationVariable($deleteClause->getAbstractSchemaName()); $deleteClause->setAliasIdentificationVariable($deleteClause->getAbstractSchemaName());
} }
$classMetadata = $this->_em->getClassMetadata($deleteClause->getAbstractSchemaName()); $classMetadata = $this->_em->getClassMetadata($deleteClause->getAbstractSchemaName());
$queryComponent = array( $queryComponent = array(
'metadata' => $classMetadata 'metadata' => $classMetadata,
'parent' => null,
'relation' => null,
'map' => null
); );
$this->_queryComponents[$deleteClause->getAliasIdentificationVariable()] = $queryComponent; $this->_queryComponents[$deleteClause->getAliasIdentificationVariable()] = $queryComponent;
...@@ -1076,18 +1088,29 @@ class Parser ...@@ -1076,18 +1088,29 @@ class Parser
/** /**
* GroupByItem ::= IdentificationVariable | SingleValuedPathExpression * GroupByItem ::= IdentificationVariable | SingleValuedPathExpression
*
* @todo Finish this implementation
*/ */
public function GroupByItem() public function GroupByItem()
{ {
// We need to check if we are in a IdentificationVariable or SingleValuedPathExpression
$glimpse = $this->_lexer->glimpse();
if ($glimpse['value'] != '.') {
$identificationVariable = $this->IdentificationVariable();
// Validate if IdentificationVariable is defined
$this->_validateIdentificationVariable($identificationVariable);
return $identificationVariable;
}
return $this->SingleValuedPathExpression(); return $this->SingleValuedPathExpression();
} }
/** /**
* OrderByItem ::= (ResultVariable | StateFieldPathExpression) ["ASC" | "DESC"] * OrderByItem ::= (ResultVariable | StateFieldPathExpression) ["ASC" | "DESC"]
* *
* @todo Support general SingleValuedPathExpression instead of only StateFieldPathExpression. * @todo Post 2.0 release. Support general SingleValuedPathExpression instead
* of only StateFieldPathExpression.
*/ */
public function OrderByItem() public function OrderByItem()
{ {
...@@ -1097,7 +1120,8 @@ class Parser ...@@ -1097,7 +1120,8 @@ class Parser
if ($glimpse['value'] != '.') { if ($glimpse['value'] != '.') {
$expr = $this->ResultVariable(); $expr = $this->ResultVariable();
// @todo Check if ResultVariable is defined somewhere // Check if ResultVariable is defined in query components
$this->_validateIdentificationVariable($expr);
} else { } else {
$expr = $this->StateFieldPathExpression(); $expr = $this->StateFieldPathExpression();
} }
...@@ -1178,13 +1202,12 @@ class Parser ...@@ -1178,13 +1202,12 @@ class Parser
$peek = $this->_lexer->glimpse(); $peek = $this->_lexer->glimpse();
if ($peek['value'] == '.') { if ($peek['value'] == '.') {
$subselectIdentificationVarDecl = new AST\SubselectIdentificationVariableDeclaration; $subselectIdVarDecl = new AST\SubselectIdentificationVariableDeclaration;
$subselectIdentificationVarDecl->setAssociationPathExpression($this->AssociationPathExpression()); $subselectIdVarDecl->setAssociationPathExpression($this->AssociationPathExpression());
$this->match(Lexer::T_AS); $this->match(Lexer::T_AS);
$this->match(Lexer::T_IDENTIFIER); $subselectIdVarDecl->setAliasIdentificationVariable($this->AliasIdentificationVariable());
$subselectIdentificationVarDecl->setAliasIdentificationVariable($this->_lexer->token['value']);
return $subselectIdentificationVarDecl; return $subselectIdVarDecl;
} }
return $this->IdentificationVariableDeclaration(); return $this->IdentificationVariableDeclaration();
...@@ -1279,7 +1302,7 @@ class Parser ...@@ -1279,7 +1302,7 @@ class Parser
'metadata' => $this->_em->getClassMetadata($targetClassName), 'metadata' => $this->_em->getClassMetadata($targetClassName),
'parent' => $joinPathExpression->getIdentificationVariable(), 'parent' => $joinPathExpression->getIdentificationVariable(),
'relation' => $parentClass->getAssociationMapping($assocField), 'relation' => $parentClass->getAssociationMapping($assocField),
'map' => null 'map' => null,
); );
$this->_queryComponents[$aliasIdentificationVariable] = $joinQueryComponent; $this->_queryComponents[$aliasIdentificationVariable] = $joinQueryComponent;
...@@ -1350,7 +1373,12 @@ class Parser ...@@ -1350,7 +1373,12 @@ class Parser
} }
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) { if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$fieldAliasIdentificationVariable = $this->ResultVariable(); $resultVariable = $this->ResultVariable();
// Include ResultVariable in query components.
$this->_queryComponents[$resultVariable] = array(
'resultvariable' => $expression
);
} }
} else { } else {
// Deny hydration of partial objects if doctrine.forcePartialLoad query hint not defined // Deny hydration of partial objects if doctrine.forcePartialLoad query hint not defined
...@@ -1392,7 +1420,13 @@ class Parser ...@@ -1392,7 +1420,13 @@ class Parser
} }
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) { if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$expr->setFieldIdentificationVariable($this->ResultVariable()); $resultVariable = $this->ResultVariable();
$expr->setFieldIdentificationVariable($resultVariable);
// Include ResultVariable in query components.
$this->_queryComponents[$resultVariable] = array(
'resultvariable' => $expr
);
} }
return $expr; return $expr;
...@@ -1449,7 +1483,6 @@ class Parser ...@@ -1449,7 +1483,6 @@ class Parser
/** /**
* ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" * ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")"
* @todo Implementation incomplete: Recognition of SimpleConditionalExpression is incomplete.
*/ */
public function ConditionalPrimary() public function ConditionalPrimary()
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment