diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index a7fb149bf..ec4907ec6 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -1583,7 +1583,7 @@ Scalar and Type Expressions .. code-block:: php ScalarExpression ::= SimpleArithmeticExpression | StringPrimary | DateTimePrimary | StateFieldPathExpression | BooleanPrimary | CaseExpression | InstanceOfExpression - StringExpression ::= StringPrimary | "(" Subselect ")" + StringExpression ::= StringPrimary | ResultVariable | "(" Subselect ")" StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression | CaseExpression BooleanExpression ::= BooleanPrimary | "(" Subselect ")" BooleanPrimary ::= StateFieldPathExpression | boolean | InputParameter diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index d2d116c03..5c721a1d5 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -2776,23 +2776,29 @@ class Parser } /** - * StringExpression ::= StringPrimary | "(" Subselect ")" + * StringExpression ::= StringPrimary | ResultVariable | "(" Subselect ")" * * @return \Doctrine\ORM\Query\AST\StringPrimary | - * \Doctrine\ORM\Query\AST\Subselect + * \Doctrine\ORM\Query\AST\Subselect | + * string */ public function StringExpression() { - if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { - $peek = $this->lexer->glimpse(); + $peek = $this->lexer->glimpse(); - if ($peek['type'] === Lexer::T_SELECT) { - $this->match(Lexer::T_OPEN_PARENTHESIS); - $expr = $this->Subselect(); - $this->match(Lexer::T_CLOSE_PARENTHESIS); + // Subselect + if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS) && $peek['type'] === Lexer::T_SELECT) { + $this->match(Lexer::T_OPEN_PARENTHESIS); + $expr = $this->Subselect(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); - return $expr; - } + return $expr; + } + + // ResultVariable (string) + if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER) && + isset($this->queryComponents[$this->lexer->lookahead['value']]['resultVariable'])) { + return $this->ResultVariable(); } return $this->StringPrimary(); diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index c92577f6f..31cb7a0d0 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -1944,8 +1944,8 @@ class SqlWalker implements TreeWalker */ public function walkNullComparisonExpression($nullCompExpr) { - $expression = $nullCompExpr->expression; - $comparison = ' IS' . ($nullCompExpr->not ? ' NOT' : '') . ' NULL'; + $expression = $nullCompExpr->expression; + $comparison = ' IS' . ($nullCompExpr->not ? ' NOT' : '') . ' NULL'; // Handle ResultVariable if (is_string($expression) && isset($this->queryComponents[$expression]['resultVariable'])) { @@ -2001,9 +2001,7 @@ class SqlWalker implements TreeWalker $sqlParameterList = array(); foreach ($instanceOfExpr->value as $parameter) { - if ($parameter instanceof AST\InputParameter) { - $this->rsm->addMetadataParameterMapping($parameter->name, 'discriminatorValue'); $sqlParameterList[] = $this->walkInputParameter($parameter); @@ -2073,7 +2071,9 @@ class SqlWalker implements TreeWalker { $sql = $this->walkArithmeticExpression($betweenExpr->expression); - if ($betweenExpr->not) $sql .= ' NOT'; + if ($betweenExpr->not) { + $sql .= ' NOT'; + } $sql .= ' BETWEEN ' . $this->walkArithmeticExpression($betweenExpr->leftBetweenExpression) . ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression); @@ -2087,14 +2087,18 @@ class SqlWalker implements TreeWalker public function walkLikeExpression($likeExpr) { $stringExpr = $likeExpr->stringExpression; - $sql = $stringExpr->dispatch($this) . ($likeExpr->not ? ' NOT' : '') . ' LIKE '; + $leftExpr = (is_string($stringExpr) && isset($this->queryComponents[$stringExpr]['resultVariable'])) + ? $this->walkResultVariable($stringExpr) + : $stringExpr->dispatch($this); + + $sql = $leftExpr . ($likeExpr->not ? ' NOT' : '') . ' LIKE '; if ($likeExpr->stringPattern instanceof AST\InputParameter) { $inputParam = $likeExpr->stringPattern; $dqlParamKey = $inputParam->name; $this->parserResult->addParameterMapping($dqlParamKey, $this->sqlParamIndex++); $sql .= '?'; - } elseif ($likeExpr->stringPattern instanceof AST\Functions\FunctionNode ) { + } elseif ($likeExpr->stringPattern instanceof AST\Functions\FunctionNode) { $sql .= $this->walkFunction($likeExpr->stringPattern); } elseif ($likeExpr->stringPattern instanceof AST\PathExpression) { $sql .= $this->walkPathExpression($likeExpr->stringPattern); diff --git a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php index ca9085457..97ad6ac8e 100644 --- a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php +++ b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php @@ -598,6 +598,14 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase { $this->assertValidDQL("SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u HAVING u.username IS NULL"); } + + /** + * @gorup DDC-1858 + */ + public function testHavingSupportLikeExpression() + { + $this->assertValidDQL("SELECT _u.id, count(_articles) as uuuu FROM Doctrine\Tests\Models\CMS\CmsUser _u LEFT JOIN _u.articles _articles GROUP BY _u HAVING uuuu LIKE '3'"); + } } /** @Entity */ diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 6aa366b67..2587905ed 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -2142,6 +2142,17 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ); } + /** + * @group DDC-1858 + */ + public function testHavingSupportResultVariableLikeExpression() + { + $this->assertSqlGeneration( + "SELECT u.name AS foo FROM Doctrine\Tests\Models\CMS\CmsUser u HAVING foo LIKE '3'", + "SELECT c0_.name AS name0 FROM cms_users c0_ HAVING name0 LIKE '3'" + ); + } + /** * @group DDC-1858 */