diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index e670c7fa2..c72a1889e 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -55,6 +55,26 @@ abstract class AbstractPlatform */ const CREATE_FOREIGNKEYS = 2; + /** + * @var int + */ + const TRIM_UNSPECIFIED = 0; + + /** + * @var int + */ + const TRIM_LEADING = 1; + + /** + * @var int + */ + const TRIM_TRAILING = 2; + + /** + * @var int + */ + const TRIM_BOTH = 3; + /** * Constructor. */ @@ -230,15 +250,27 @@ abstract class AbstractPlatform } /** - * trim - * returns the string $str with leading and proceeding space characters removed + * Trim a string, leading/trailing/both and with a given char which defaults to space. * - * @param string $str literal string or column name + * @param string $str + * @param int $pos + * @param string $char has to be quoted already * @return string */ - public function getTrimExpression($str) + public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) { - return 'TRIM(' . $str . ')'; + $posStr = ''; + $trimChar = ($char != false) ? $char . ' FROM ' : ''; + + if ($pos == self::TRIM_LEADING) { + $posStr = 'LEADING '.$trimChar; + } else if($pos == self::TRIM_TRAILING) { + $posStr = 'TRAILING '.$trimChar; + } else if($pos == self::TRIM_BOTH) { + $posStr = 'BOTH '.$trimChar; + } + + return 'TRIM(' . $posStr . $str . ')'; } /** diff --git a/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php b/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php index 0255ce9b9..9ab6a0f4e 100644 --- a/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php @@ -64,6 +64,30 @@ class SqlitePlatform extends AbstractPlatform } } + /** + * Trim a string, leading/trailing/both and with a given char which defaults to space. + * + * @param string $str + * @param int $pos + * @param string $char + * @return string + */ + public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) + { + $trimFn = ''; + $trimChar = ($char != false) ? (', ' . $char) : ''; + + if ($pos == self::TRIM_LEADING) { + $trimFn = 'LTRIM'; + } else if($pos == self::TRIM_TRAILING) { + $trimFn = 'RTRIM'; + } else { + $trimFn = 'TRIM'; + } + + return $trimFn . '(' . $str . $trimChar . ')'; + } + /** * return string to call a function to get a substring inside an SQL statement * diff --git a/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php index a70600919..cea68920a 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php @@ -22,6 +22,7 @@ namespace Doctrine\ORM\Query\AST\Functions; use Doctrine\ORM\Query\Lexer; +use Doctrine\DBAL\Platforms\AbstractPlatform; /** * "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" @@ -39,7 +40,7 @@ class TrimFunction extends FunctionNode public $leading; public $trailing; public $both; - public $trimChar; + public $trimChar = false; public $stringPrimary; /** @@ -47,21 +48,20 @@ class TrimFunction extends FunctionNode */ public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) { - $sql = 'TRIM('; - + $pos = AbstractPlatform::TRIM_UNSPECIFIED; if ($this->leading) { - $sql .= 'LEADING '; + $pos = AbstractPlatform::TRIM_LEADING; } else if ($this->trailing) { - $sql .= 'TRAILING '; + $pos = AbstractPlatform::TRIM_TRAILING; } else if ($this->both) { - $sql .= 'BOTH '; + $pos = AbstractPlatform::TRIM_BOTH; } - - if ($this->trimChar) { - $sql .= $sqlWalker->getConnection()->quote($this->trimChar) . ' '; - } - - return $sql . 'FROM ' . $sqlWalker->walkStringPrimary($this->stringPrimary) . ')'; + + return $sqlWalker->getConnection()->getDatabasePlatform()->getTrimExpression( + $sqlWalker->walkStringPrimary($this->stringPrimary), + $pos, + ($this->trimChar != false) ? $sqlWalker->getConnection()->quote($this->trimChar) : false + ); } /** @@ -70,7 +70,7 @@ class TrimFunction extends FunctionNode public function parse(\Doctrine\ORM\Query\Parser $parser) { $lexer = $parser->getLexer(); - + $parser->match(Lexer::T_IDENTIFIER); $parser->match(Lexer::T_OPEN_PARENTHESIS); @@ -95,8 +95,8 @@ class TrimFunction extends FunctionNode } $this->stringPrimary = $parser->StringPrimary(); - + $parser->match(Lexer::T_CLOSE_PARENTHESIS); } - + } diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php index d58e29cb5..2b2a4cfae 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php @@ -184,8 +184,6 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase public function testFunctionTrim() { - $this->markTestIncomplete('Trim has problems on MySql (3rd Case).'); - $dql = "SELECT m, TRIM(TRAILING '.' FROM m.name) AS str1, ". " TRIM(LEADING '.' FROM m.name) AS str2, TRIM(CONCAT(' ', CONCAT(m.name, ' '))) AS str3 ". "FROM Doctrine\Tests\Models\Company\CompanyManager m"; diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 37857e64d..973104cf1 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -223,7 +223,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase "SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE TRIM(u.name) = 'someone'", // String quoting in the SQL usually depends on the database platform. // This test works with a mock connection which uses ' for string quoting. - "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE TRIM(FROM c0_.name) = 'someone'" + "SELECT c0_.name AS name0 FROM cms_users c0_ WHERE TRIM(c0_.name) = 'someone'" ); }