diff --git a/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php new file mode 100644 index 000000000..1ee823337 --- /dev/null +++ b/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php @@ -0,0 +1,63 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "BIT_AND" "(" ArithmeticPrimary "," ArithmeticPrimary ")" + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Fabio B. Silva + */ +class BitAndFunction extends FunctionNode +{ + public $firstArithmetic; + public $secondArithmetic; + + /** + * @override + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + $platform = $sqlWalker->getConnection()->getDatabasePlatform(); + return $platform->getBitAndComparisonExpression( + $this->firstArithmetic->dispatch($sqlWalker), + $this->secondArithmetic->dispatch($sqlWalker) + ); + } + + /** + * @override + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstArithmetic = $parser->ArithmeticPrimary(); + $parser->match(Lexer::T_COMMA); + $this->secondArithmetic = $parser->ArithmeticPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php new file mode 100644 index 000000000..ba36e97aa --- /dev/null +++ b/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php @@ -0,0 +1,63 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "BIT_OR" "(" ArithmeticPrimary "," ArithmeticPrimary ")" + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Fabio B. Silva + */ +class BitOrFunction extends FunctionNode +{ + public $firstArithmetic; + public $secondArithmetic; + + /** + * @override + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + $platform = $sqlWalker->getConnection()->getDatabasePlatform(); + return $platform->getBitOrComparisonExpression( + $this->firstArithmetic->dispatch($sqlWalker), + $this->secondArithmetic->dispatch($sqlWalker) + ); + } + + /** + * @override + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstArithmetic = $parser->ArithmeticPrimary(); + $parser->match(Lexer::T_COMMA); + $this->secondArithmetic = $parser->ArithmeticPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index 4c1bd50e1..234444226 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -53,6 +53,8 @@ class Parser 'mod' => 'Doctrine\ORM\Query\AST\Functions\ModFunction', 'size' => 'Doctrine\ORM\Query\AST\Functions\SizeFunction', 'date_diff' => 'Doctrine\ORM\Query\AST\Functions\DateDiffFunction', + 'bit_and' => 'Doctrine\ORM\Query\AST\Functions\BitAndFunction', + 'bit_or' => 'Doctrine\ORM\Query\AST\Functions\BitOrFunction', ); /** READ-ONLY: Maps BUILT-IN datetime function names to AST class names. */ diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php index e37ea9f62..9841dfeb7 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php @@ -317,6 +317,54 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertTrue(strtotime($arg[0]['add']) > 0); } + /** + * @group DDC-1213 + */ + public function testBitOrComparison() + { + $dql = 'SELECT m, ' . + 'BIT_OR(4, 2) AS bit_or,' . + 'BIT_OR( (m.salary/100000) , 2 ) AS salary_bit_or ' . + 'FROM Doctrine\Tests\Models\Company\CompanyManager m ' . + 'ORDER BY ' . + 'm.id ' ; + $result = $this->_em->createQuery($dql)->getArrayResult(); + + $this->assertEquals(4 | 2, $result[0]['bit_or']); + $this->assertEquals(4 | 2, $result[1]['bit_or']); + $this->assertEquals(4 | 2, $result[2]['bit_or']); + $this->assertEquals(4 | 2, $result[3]['bit_or']); + + $this->assertEquals(($result[0][0]['salary']/100000) | 2, $result[0]['salary_bit_or']); + $this->assertEquals(($result[1][0]['salary']/100000) | 2, $result[1]['salary_bit_or']); + $this->assertEquals(($result[2][0]['salary']/100000) | 2, $result[2]['salary_bit_or']); + $this->assertEquals(($result[3][0]['salary']/100000) | 2, $result[3]['salary_bit_or']); + } + + /** + * @group DDC-1213 + */ + public function testBitAndComparison() + { + $dql = 'SELECT m, ' . + 'BIT_AND(4, 2) AS bit_and,' . + 'BIT_AND( (m.salary/100000) , 2 ) AS salary_bit_and ' . + 'FROM Doctrine\Tests\Models\Company\CompanyManager m ' . + 'ORDER BY ' . + 'm.id ' ; + $result = $this->_em->createQuery($dql)->getArrayResult(); + + $this->assertEquals(4 & 2, $result[0]['bit_and']); + $this->assertEquals(4 & 2, $result[1]['bit_and']); + $this->assertEquals(4 & 2, $result[2]['bit_and']); + $this->assertEquals(4 & 2, $result[3]['bit_and']); + + $this->assertEquals(($result[0][0]['salary']/100000) & 2, $result[0]['salary_bit_and']); + $this->assertEquals(($result[1][0]['salary']/100000) & 2, $result[1]['salary_bit_and']); + $this->assertEquals(($result[2][0]['salary']/100000) & 2, $result[2]['salary_bit_and']); + $this->assertEquals(($result[3][0]['salary']/100000) & 2, $result[3]['salary_bit_and']); + } + protected function generateFixture() { $manager1 = new CompanyManager(); diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 7a7b7cd3f..a71f9f25d 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -1392,6 +1392,29 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ); } + /** + * @group DDC-1213 + */ + public function testSupportsBitComparison() + { + $this->assertSqlGeneration( + 'SELECT BIT_OR(4,2), BIT_AND(4,2), u FROM Doctrine\Tests\Models\CMS\CmsUser u', + 'SELECT (4 | 2) AS sclr0, (4 & 2) AS sclr1, c0_.id AS id2, c0_.status AS status3, c0_.username AS username4, c0_.name AS name5 FROM cms_users c0_' + ); + $this->assertSqlGeneration( + 'SELECT BIT_OR(u.id,2), BIT_AND(u.id,2) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE BIT_OR(u.id,2) > 0', + 'SELECT (c0_.id | 2) AS sclr0, (c0_.id & 2) AS sclr1 FROM cms_users c0_ WHERE (c0_.id | 2) > 0' + ); + $this->assertSqlGeneration( + 'SELECT BIT_OR(u.id,2), BIT_AND(u.id,2) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE BIT_AND(u.id , 4) > 0', + 'SELECT (c0_.id | 2) AS sclr0, (c0_.id & 2) AS sclr1 FROM cms_users c0_ WHERE (c0_.id & 4) > 0' + ); + $this->assertSqlGeneration( + 'SELECT BIT_OR(u.id,2), BIT_AND(u.id,2) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE BIT_OR(u.id , 2) > 0 OR BIT_AND(u.id , 4) > 0', + 'SELECT (c0_.id | 2) AS sclr0, (c0_.id & 2) AS sclr1 FROM cms_users c0_ WHERE (c0_.id | 2) > 0 OR (c0_.id & 4) > 0' + ); + } + public function testCustomTypeValueSql() { if (DBALType::hasType('negative_to_positive')) {