From b9f744893efa3517054fd92ac49ce1cf36971fed Mon Sep 17 00:00:00 2001 From: romanb Date: Tue, 13 Oct 2009 10:48:46 +0000 Subject: [PATCH] [2.0][DDC-42] Fixed. --- lib/Doctrine/DBAL/DriverManager.php | 7 +--- .../DBAL/Platforms/AbstractPlatform.php | 5 ++- lib/Doctrine/ORM/Query/AST/Literal.php | 24 ++++++++++++ lib/Doctrine/ORM/Query/AST/Node.php | 2 +- lib/Doctrine/ORM/Query/Parser.php | 20 +++++----- lib/Doctrine/ORM/Query/SqlWalker.php | 30 ++++++++++----- .../ORM/Query/LanguageRecognitionTest.php | 5 +++ .../ORM/Query/SelectSqlGenerationTest.php | 38 +++++++++++++++++++ 8 files changed, 102 insertions(+), 29 deletions(-) create mode 100644 lib/Doctrine/ORM/Query/AST/Literal.php diff --git a/lib/Doctrine/DBAL/DriverManager.php b/lib/Doctrine/DBAL/DriverManager.php index fe07ba526..124a87d11 100644 --- a/lib/Doctrine/DBAL/DriverManager.php +++ b/lib/Doctrine/DBAL/DriverManager.php @@ -36,15 +36,14 @@ final class DriverManager * List of supported drivers and their mappings to the driver classes. * * @var array + * @todo REMOVE. Users should directly supply class names instead. */ private static $_driverMap = array( 'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver', 'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver', 'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver', 'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver', - 'pdo_mssql' => 'Doctrine\DBAL\Driver\PDOMsSql\Driver', - 'pdo_firebird' => 'Doctrine\DBAL\Driver\PDOFirebird\Driver', - 'pdo_informix' => 'Doctrine\DBAL\Driver\PDOInformix\Driver', + 'pdo_mssql' => 'Doctrine\DBAL\Driver\PDOMsSql\Driver' ); /** Private constructor. This class cannot be instantiated. */ @@ -66,8 +65,6 @@ final class DriverManager * pdo_pgsql * pdo_oracle * pdo_mssql - * pdo_firebird - * pdo_informix * * OR 'driverClass' that contains the full class name (with namespace) of the * driver class to instantiate. diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 977353179..2338377fa 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -1151,9 +1151,10 @@ abstract class AbstractPlatform /** * Some platforms need the boolean values to be converted. - * Default conversion defined here converts to integers. + * + * The default conversion in this implementation converts to integers (false => 0, true => 1). * - * @param array $item + * @param mixed $item */ public function convertBooleans($item) { diff --git a/lib/Doctrine/ORM/Query/AST/Literal.php b/lib/Doctrine/ORM/Query/AST/Literal.php new file mode 100644 index 000000000..d3acb9625 --- /dev/null +++ b/lib/Doctrine/ORM/Query/AST/Literal.php @@ -0,0 +1,24 @@ +type = $type; + $this->value = $value; + } + + public function dispatch($walker) + { + return $walker->walkLiteral($this); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/AST/Node.php b/lib/Doctrine/ORM/Query/AST/Node.php index 442a7e73a..6d77a6701 100644 --- a/lib/Doctrine/ORM/Query/AST/Node.php +++ b/lib/Doctrine/ORM/Query/AST/Node.php @@ -34,7 +34,7 @@ namespace Doctrine\ORM\Query\AST; */ abstract class Node { - abstract public function dispatch($sqlWalker); + abstract public function dispatch($walker); /** * Dumps the AST Node into a string representation for information purpose only diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index f086351a5..a85b5a48a 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -1875,12 +1875,16 @@ class Parser { switch ($this->_lexer->lookahead['type']) { case Lexer::T_STRING: + $this->match($this->_lexer->lookahead['value']); + return new AST\Literal(AST\Literal::STRING, $this->_lexer->token['value']); case Lexer::T_INTEGER: case Lexer::T_FLOAT: $this->match($this->_lexer->lookahead['value']); - - return $this->_lexer->token['value']; - + return new AST\Literal(AST\Literal::NUMERIC, $this->_lexer->token['value']); + case Lexer::T_TRUE: + case Lexer::T_FALSE: + $this->match($this->_lexer->lookahead['value']); + return new AST\Literal(AST\Literal::BOOLEAN, $this->_lexer->token['value']); default: $this->syntaxError('Literal'); } @@ -2040,11 +2044,6 @@ class Parser case Lexer::T_INPUT_PARAMETER: return $this->InputParameter(); - case Lexer::T_STRING: - case Lexer::T_INTEGER: - case Lexer::T_FLOAT: - return $this->Literal(); - default: $peek = $this->_lexer->glimpse(); @@ -2054,10 +2053,9 @@ class Parser } return $this->FunctionDeclaration(); + } else { + return $this->Literal(); } - - $this->syntaxError(); - break; } } diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 121ddaf02..d0328cfa5 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -1338,13 +1338,20 @@ class SqlWalker implements TreeWalker if ($inExpr->subselect) { $sql .= $this->walkSubselect($inExpr->subselect); } else { - $sql .= implode(', ', array_map(array($this, 'walkLiteral'), $inExpr->literals)); + $sql .= implode(', ', array_map(array($this, 'walkInParameter'), $inExpr->literals)); } $sql .= ')'; return $sql; } + + public function walkInParameter($inParam) + { + return $inParam instanceof AST\InputParameter ? + $this->walkInputParameter($inParam) : + $this->walkLiteral($inParam); + } /** * Walks down a literal that represents an AST node, thereby generating the appropriate SQL. @@ -1354,11 +1361,18 @@ class SqlWalker implements TreeWalker */ public function walkLiteral($literal) { - if ($literal instanceof AST\InputParameter) { - return $this->walkInputParameter($literal); + switch ($literal->type) { + case AST\Literal::STRING: + return $this->_conn->quote($literal->value); + case AST\Literal::BOOLEAN: + $bool = strtolower($literal->value) == 'true' ? true : false; + $boolVal = $this->_conn->getDatabasePlatform()->convertBooleans($bool); + return is_string($boolVal) ? $this->_conn->quote($boolVal) : $boolVal; + case AST\Literal::NUMERIC: + return $literal->value; + default: + throw QueryException::invalidLiteral($literal); } - - return $literal; //TODO: quote() ? } /** @@ -1513,11 +1527,7 @@ class SqlWalker implements TreeWalker $sql = ($factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : '')); $primary = $factor->arithmeticPrimary; - if (is_numeric($primary)) { - $sql .= $primary; - } else if (is_string($primary)) { - $sql .= $this->_conn->quote($primary); - } else if ($primary instanceof AST\SimpleArithmeticExpression) { + if ($primary instanceof AST\SimpleArithmeticExpression) { $sql .= '(' . $this->walkSimpleArithmeticExpression($primary) . ')'; } else if ($primary instanceof AST\Node) { $sql .= $primary->dispatch($this); diff --git a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php index 6807a0ff5..4cc6dedde 100644 --- a/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php +++ b/tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php @@ -346,6 +346,11 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase $this->assertValidDql('SELECT p FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.user = ?1'); } + public function testBooleanLiteralInWhere() + { + $this->assertValidDql('SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = true'); + } + /** * This checks for invalid attempt to hydrate a proxy. It should throw an exception * diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index ef3069b91..7bda4a04f 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -416,6 +416,44 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ); } + + public function testBooleanLiteralInWhereOnSqlite() + { + $oldPlat = $this->_em->getConnection()->getDatabasePlatform(); + $this->_em->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\SqlitePlatform); + + $this->assertSqlGeneration( + "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = true", + "SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 1" + ); + + $this->assertSqlGeneration( + "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = false", + "SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 0" + ); + + $this->_em->getConnection()->setDatabasePlatform($oldPlat); + } + + public function testBooleanLiteralInWhereOnPostgres() + { + $oldPlat = $this->_em->getConnection()->getDatabasePlatform(); + $this->_em->getConnection()->setDatabasePlatform(new \Doctrine\DBAL\Platforms\PostgreSqlPlatform); + + $this->assertSqlGeneration( + "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = true", + "SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 'true'" + ); + + $this->assertSqlGeneration( + "SELECT b FROM Doctrine\Tests\Models\Generic\BooleanModel b WHERE b.booleanField = false", + "SELECT b0_.id AS id0, b0_.booleanField AS booleanField1 FROM boolean_model b0_ WHERE b0_.booleanField = 'false'" + ); + + $this->_em->getConnection()->setDatabasePlatform($oldPlat); + } + + /* Not yet implemented, needs more thought public function testSingleValuedAssociationFieldInWhere() {