Commit 6bfbab9f authored by beberlei's avatar beberlei

[2.0] DDC-325 - Fixed LOCATE() support for all platforms.

parent 371f3d5e
......@@ -34,6 +34,7 @@ class Driver implements \Doctrine\DBAL\Driver
protected $_userDefinedFunctions = array(
'sqrt' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfSqrt'), 'numArgs' => 1),
'mod' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfMod'), 'numArgs' => 2),
'locate' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfLocate'), 'numArgs' => -1),
);
/**
......
......@@ -324,16 +324,16 @@ abstract class AbstractPlatform
}
/**
* locate
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr)
public function getLocateExpression($str, $substr, $startPos = false)
{
return 'LOCATE(' . $str . ', ' . $substr . ')';
throw DBALException::notSupported(__METHOD__);
}
/**
......
......@@ -68,6 +68,23 @@ class MySqlPlatform extends AbstractPlatform
return 'UUID()';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE(' . $substr . ', ' . $str . ')';
} else {
return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')';
}
}
/**
* Returns a series of strings concatinated
*
......
......@@ -74,6 +74,23 @@ class OraclePlatform extends AbstractPlatform
}
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'INSTR('.$str.', '.$substr.')';
} else {
return 'INSTR('.$str.', '.$substr.', '.$startPos.')';
}
}
/**
* Returns global unique identifier
*
......
......@@ -74,6 +74,24 @@ class PostgreSqlPlatform extends AbstractPlatform
return 'SIMILAR TO';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos !== false) {
$str = $this->getSubstringExpression($str, $startPos);
return 'CASE WHEN (POSITION('.$substr.' IN '.$str.') = 0) THEN 0 ELSE (POSITION('.$substr.' IN '.$str.') + '.($startPos-1).') END';
} else {
return 'POSITION('.$substr.' IN '.$str.')';
}
}
/**
* parses a literal boolean value and returns
* proper sql equivalent
......
......@@ -109,6 +109,23 @@ class SqlitePlatform extends AbstractPlatform
return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))';
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE('.$str.', '.$substr.')';
} else {
return 'LOCATE('.$str.', '.$substr.', '.$startPos.')';
}
}
protected function _getTransactionIsolationLevelSql($level)
{
switch ($level) {
......@@ -403,4 +420,18 @@ class SqlitePlatform extends AbstractPlatform
{
return ($a % $b);
}
/**
* @param string $str
* @param string $substr
* @param int $offset
*/
static public function udfLocate($str, $substr, $offset = 0)
{
$pos = strpos($str, $substr, $offset);
if ($pos !== false) {
return $pos+1;
}
return 0;
}
}
......@@ -38,20 +38,22 @@ class LocateFunction extends FunctionNode
{
public $firstStringPrimary;
public $secondStringPrimary;
public $simpleArithmeticExpression;
public $simpleArithmeticExpression = false;
/**
* @override
*/
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
//TODO: Use platform to get SQL
return 'LOCATE(' . $sqlWalker->walkStringPrimary($this->firstStringPrimary) . ', '
. $sqlWalker->walkStringPrimary($this->secondStringPrimary)
. (($this->simpleArithmeticExpression)
? ', ' . $sqlWalker->walkSimpleArithmeticExpression($this->simpleArithmeticExpression)
: ''
) . ')';
return $sqlWalker->getConnection()->getDatabasePlatform()->getLocateExpression(
$sqlWalker->walkStringPrimary($this->firstStringPrimary),
$sqlWalker->walkStringPrimary($this->secondStringPrimary),
(($this->simpleArithmeticExpression)
? $sqlWalker->walkSimpleArithmeticExpression($this->simpleArithmeticExpression)
: false
)
);
}
/**
......
......@@ -99,16 +99,21 @@ class QueryDqlFunctionTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testFunctionLocate()
{
$this->markTestIncomplete('Locate is not working equally across platforms, needs some work.');
$dql = "SELECT m, LOCATE(LOWER(m.name), 'e') AS loc, LOCATE(LOWER(m.name), 'e', 7) AS loc2 ".
"FROM Doctrine\Tests\Models\Company\CompanyManager m";
$result = $this->_em->createQuery("SELECT m, LOCATE(m.name, 'e') AS locate FROM Doctrine\Tests\Models\Company\CompanyManager m")
$result = $this->_em->createQuery($dql)
->getArrayResult();
$this->assertEquals(4, count($result));
$this->assertEquals(0, $result[0]['locate']);
$this->assertEquals(2, $result[1]['locate']);
$this->assertEquals(10, $result[2]['locate']);
$this->assertEquals(25, $result[3]['locate']);
$this->assertEquals(0, $result[0]['loc']);
$this->assertEquals(2, $result[1]['loc']);
$this->assertEquals(6, $result[2]['loc']);
$this->assertEquals(0, $result[3]['loc']);
$this->assertEquals(0, $result[0]['loc2']);
$this->assertEquals(10, $result[1]['loc2']);
$this->assertEquals(9, $result[2]['loc2']);
$this->assertEquals(0, $result[3]['loc2']);
}
public function testFunctionLower()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment