1
0
Fork 0
mirror of synced 2025-04-03 13:23:37 +03:00

DDC-1696 Allowed Strings to be used inside of Case expressions. It seems this fixes other misterious use cases not yet identified by us.

This commit is contained in:
Guilherme Blanco 2012-03-11 21:14:08 -04:00
parent 0a78f7bc11
commit 7954386705
5 changed files with 58 additions and 39 deletions

View file

@ -30,6 +30,7 @@ use Doctrine\ORM\Query\QueryException;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
*/ */
class DateAddFunction extends FunctionNode class DateAddFunction extends FunctionNode
@ -40,19 +41,23 @@ class DateAddFunction extends FunctionNode
public function getSql(SqlWalker $sqlWalker) public function getSql(SqlWalker $sqlWalker)
{ {
$unit = strtolower($this->unit); switch (strtolower($this->unit->value)) {
if ($unit == "day") { case 'day':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddDaysExpression( return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddDaysExpression(
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker) $this->intervalExpression->dispatch($sqlWalker)
); );
} else if ($unit == "month") {
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression( case 'month':
$this->firstDateExpression->dispatch($sqlWalker), return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression(
$this->intervalExpression->dispatch($sqlWalker) $this->firstDateExpression->dispatch($sqlWalker),
); $this->intervalExpression->dispatch($sqlWalker)
} else { );
throw QueryException::semanticalError('DATE_ADD() only supports units of type day and month.');
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(); $this->intervalExpression = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA); $parser->match(Lexer::T_COMMA);
$this->unit = $parser->StringPrimary(); $this->unit = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS); $parser->match(Lexer::T_CLOSE_PARENTHESIS);
} }
} }

View file

@ -30,29 +30,30 @@ use Doctrine\ORM\Query\QueryException;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
*/ */
class DateSubFunction extends DateAddFunction class DateSubFunction extends DateAddFunction
{ {
public $firstDateExpression = null;
public $intervalExpression = null;
public $unit = null;
public function getSql(SqlWalker $sqlWalker) public function getSql(SqlWalker $sqlWalker)
{ {
$unit = strtolower($this->unit); switch (strtolower($this->unit->value)) {
if ($unit == "day") { case 'day':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubDaysExpression( return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubDaysExpression(
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker) $this->intervalExpression->dispatch($sqlWalker)
); );
} else if ($unit == "month") {
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression( case 'month':
$this->firstDateExpression->dispatch($sqlWalker), return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression(
$this->intervalExpression->dispatch($sqlWalker) $this->firstDateExpression->dispatch($sqlWalker),
); $this->intervalExpression->dispatch($sqlWalker)
} else { );
throw QueryException::semanticalError('DATE_SUB() only supports units of type day and month.');
default:
throw QueryException::semanticalError(
'DATE_SUB() only supports units of type day and month.'
);
} }
} }
} }

View file

@ -2574,7 +2574,7 @@ class Parser
case Lexer::T_STRING: case Lexer::T_STRING:
$this->match(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: case Lexer::T_INPUT_PARAMETER:
return $this->InputParameter(); return $this->InputParameter();
@ -2854,7 +2854,8 @@ class Parser
if ($this->_lexer->lookahead['type'] === Lexer::T_ESCAPE) { if ($this->_lexer->lookahead['type'] === Lexer::T_ESCAPE) {
$this->match(Lexer::T_ESCAPE); $this->match(Lexer::T_ESCAPE);
$this->match(Lexer::T_STRING); $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); $likeExpr = new AST\LikeExpression($stringExpr, $stringPattern, $escapeChar);

View file

@ -43,7 +43,7 @@ class SqlWalker implements TreeWalker
* @var string * @var string
*/ */
const HINT_DISTINCT = 'doctrine.distinct'; const HINT_DISTINCT = 'doctrine.distinct';
/** /**
* @var ResultSetMapping * @var ResultSetMapping
*/ */
@ -1979,11 +1979,11 @@ class SqlWalker implements TreeWalker
} elseif ($likeExpr->stringPattern instanceof AST\PathExpression) { } elseif ($likeExpr->stringPattern instanceof AST\PathExpression) {
$sql .= $this->walkPathExpression($likeExpr->stringPattern); $sql .= $this->walkPathExpression($likeExpr->stringPattern);
} else { } else {
$sql .= $this->_conn->quote($likeExpr->stringPattern); $sql .= $this->walkLiteral($likeExpr->stringPattern);
} }
if ($likeExpr->escapeChar) { if ($likeExpr->escapeChar) {
$sql .= ' ESCAPE ' . $this->_conn->quote($likeExpr->escapeChar); $sql .= ' ESCAPE ' . $this->walkLiteral($likeExpr->escapeChar);
} }
return $sql; return $sql;

View file

@ -1112,7 +1112,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{ {
$this->assertSqlGeneration( $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 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( $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 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( $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 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( $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 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_"
); );
} }