From 795438670517cd7a4e76bca6dd33fdc9bbb5d988 Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Sun, 11 Mar 2012 21:14:08 -0400 Subject: [PATCH] DDC-1696 Allowed Strings to be used inside of Case expressions. It seems this fixes other misterious use cases not yet identified by us. --- .../Query/AST/Functions/DateAddFunction.php | 32 ++++++++++------- .../Query/AST/Functions/DateSubFunction.php | 35 ++++++++++--------- lib/Doctrine/ORM/Query/Parser.php | 5 +-- lib/Doctrine/ORM/Query/SqlWalker.php | 6 ++-- .../ORM/Query/SelectSqlGenerationTest.php | 19 +++++++--- 5 files changed, 58 insertions(+), 39 deletions(-) diff --git a/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php index 1d840cc49..1a4b08e6c 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php @@ -30,6 +30,7 @@ use Doctrine\ORM\Query\QueryException; * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org * @since 2.0 + * @author Guilherme Blanco * @author Benjamin Eberlei */ class DateAddFunction extends FunctionNode @@ -40,19 +41,23 @@ class DateAddFunction extends FunctionNode 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.'); + 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.' + ); } } @@ -66,6 +71,7 @@ class DateAddFunction extends FunctionNode $this->intervalExpression = $parser->ArithmeticPrimary(); $parser->match(Lexer::T_COMMA); $this->unit = $parser->StringPrimary(); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php index a608d49d4..9177cfa1c 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php @@ -30,29 +30,30 @@ use Doctrine\ORM\Query\QueryException; * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org * @since 2.0 + * @author Guilherme Blanco * @author Benjamin Eberlei */ class DateSubFunction extends DateAddFunction { - public $firstDateExpression = null; - public $intervalExpression = null; - public $unit = null; - public function getSql(SqlWalker $sqlWalker) { - $unit = strtolower($this->unit); - if ($unit == "day") { - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubDaysExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - } else if ($unit == "month") { - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - } else { - throw QueryException::semanticalError('DATE_SUB() only supports units of type day and month.'); + switch (strtolower($this->unit->value)) { + case 'day': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubDaysExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + + case 'month': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + + default: + throw QueryException::semanticalError( + 'DATE_SUB() only supports units of type day and month.' + ); } } } \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index 5122240c7..0233e4c5e 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -2574,7 +2574,7 @@ class Parser case Lexer::T_STRING: $this->match(Lexer::T_STRING); - return $this->_lexer->token['value']; + return new AST\Literal(AST\Literal::STRING, $this->_lexer->token['value']); case Lexer::T_INPUT_PARAMETER: return $this->InputParameter(); @@ -2854,7 +2854,8 @@ class Parser if ($this->_lexer->lookahead['type'] === Lexer::T_ESCAPE) { $this->match(Lexer::T_ESCAPE); $this->match(Lexer::T_STRING); - $escapeChar = $this->_lexer->token['value']; + + $escapeChar = new AST\Literal(AST\Literal::STRING, $this->_lexer->token['value']); } $likeExpr = new AST\LikeExpression($stringExpr, $stringPattern, $escapeChar); diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index a4f7fd2f2..b04d6e8d3 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -43,7 +43,7 @@ class SqlWalker implements TreeWalker * @var string */ const HINT_DISTINCT = 'doctrine.distinct'; - + /** * @var ResultSetMapping */ @@ -1979,11 +1979,11 @@ class SqlWalker implements TreeWalker } elseif ($likeExpr->stringPattern instanceof AST\PathExpression) { $sql .= $this->walkPathExpression($likeExpr->stringPattern); } else { - $sql .= $this->_conn->quote($likeExpr->stringPattern); + $sql .= $this->walkLiteral($likeExpr->stringPattern); } if ($likeExpr->escapeChar) { - $sql .= ' ESCAPE ' . $this->_conn->quote($likeExpr->escapeChar); + $sql .= ' ESCAPE ' . $this->walkLiteral($likeExpr->escapeChar); } return $sql; diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 2bec9a562..5b750462c 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -1112,7 +1112,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase { $this->assertSqlGeneration( "SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id = CASE g.name WHEN 'admin' THEN 1 ELSE 2 END", - "SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id = CASE c0_.name WHEN admin THEN 1 ELSE 2 END" + "SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id = CASE c0_.name WHEN 'admin' THEN 1 ELSE 2 END" ); } @@ -1120,7 +1120,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase { $this->assertSqlGeneration( "SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id = (CASE g.name WHEN 'admin' THEN 1 WHEN 'moderator' THEN 2 ELSE 3 END)", - "SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id = CASE c0_.name WHEN admin THEN 1 WHEN moderator THEN 2 ELSE 3 END" + "SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id = CASE c0_.name WHEN 'admin' THEN 1 WHEN 'moderator' THEN 2 ELSE 3 END" ); } @@ -1144,7 +1144,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase { $this->assertSqlGeneration( "SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE g2.name WHEN 'admin' THEN 1 ELSE 2 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)", - "SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id IN (SELECT CASE c1_.name WHEN admin THEN 1 ELSE 2 END AS sclr2 FROM cms_groups c1_)" + "SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id IN (SELECT CASE c1_.name WHEN 'admin' THEN 1 ELSE 2 END AS sclr2 FROM cms_groups c1_)" ); } @@ -1152,7 +1152,18 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase { $this->assertSqlGeneration( "SELECT g FROM Doctrine\Tests\Models\CMS\CmsGroup g WHERE g.id IN (SELECT CASE g2.name WHEN 'admin' THEN 1 WHEN 'moderator' THEN 2 ELSE 3 END FROM Doctrine\Tests\Models\CMS\CmsGroup g2)", - "SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id IN (SELECT CASE c1_.name WHEN admin THEN 1 WHEN moderator THEN 2 ELSE 3 END AS sclr2 FROM cms_groups c1_)" + "SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_groups c0_ WHERE c0_.id IN (SELECT CASE c1_.name WHEN 'admin' THEN 1 WHEN 'moderator' THEN 2 ELSE 3 END AS sclr2 FROM cms_groups c1_)" + ); + } + + /** + * @group DDC-1696 + */ + public function testSimpleCaseWithStringPrimary() + { + $this->assertSqlGeneration( + "SELECT g.id, CASE WHEN ((g.id / 2) > 18) THEN 'Foo' ELSE 'Bar' END AS test FROM Doctrine\Tests\Models\CMS\CmsGroup g", + "SELECT c0_.id AS id0, CASE WHEN (c0_.id / 2 > 18) THEN 'Foo' ELSE 'Bar' END AS sclr1 FROM cms_groups c0_" ); }